Trang bị thêm 2 - URL động


181

Với Retrofit 2, bạn có thể đặt URL đầy đủ trong chú thích của phương thức dịch vụ như:

public interface APIService {
  @GET("http://api.mysite.com/user/list")
  Call<Users> getUsers();
}

Tuy nhiên, trong ứng dụng của tôi, không biết URL của dịch vụ web của tôi tại thời điểm biên dịch, ứng dụng truy xuất chúng trong một tệp đã tải xuống nên tôi tự hỏi làm thế nào tôi có thể sử dụng Retrofit 2 với URL động đầy đủ.

Tôi đã cố gắng thiết lập một đường dẫn đầy đủ như:

public interface APIService {
  @GET("{fullUrl}")
  Call<Users> getUsers(@Path("fullUrl") fullUrl);
}

new Retrofit.Builder()
  .baseUrl("http://api.mysite.com/")
  .build()
  .create(APIService.class)
  .getUsers("http://api.mysite.com/user/list"); // this url should be dynamic
  .execute();

Nhưng ở đây, Retrofit không thấy rằng đường dẫn thực sự là một URL đầy đủ và đang cố tải xuống http://api.mysite.com/http%3A%2F%2Fapi.mysite.com%2Fuser%2Flist

Bất kỳ gợi ý về cách tôi có thể sử dụng Retrofit với url động như vậy?

Cảm ơn bạn


5
Đối với những người tìm kiếm tương lai, có một hướng dẫn về các URL động với Retrofit: futurestud.io/tutorials/...
peitek

Câu trả lời:


389

Tôi nghĩ rằng bạn đang sử dụng nó sai cách. Đây là một đoạn trích từ changelog :

Mới: chú thích tham số @Url cho phép chuyển một URL hoàn chỉnh cho điểm cuối.

Vì vậy, giao diện của bạn nên như thế này:

public interface APIService {
    @GET
    Call<Users> getUsers(@Url String url);
}

1
@ pdegand59 Đó là thương hiệu mới :) xem changelog
Yazazzello

2
Tại sao basurl được yêu cầu mặc dù url cho điểm cuối là fullurl?
Billyjoker 7/12/2015

13
Nếu tôi sử dụng chú thích @Url này. Vậy thì chúng ta nên viết gì trong .baseUrl () ??
Gulnaz Ghanchi

12
bạn nên viết url chính của bạn. Tham số @Url sẽ ghi đè lên bằng mọi cách.
Yazazzello

5
Tôi đã thử thêm URL như ở trên nhưng baseUrl mà tôi thường đặt cho trình xây dựng trang bị thêm vào toàn bộ url tôi đã chỉ định trong tham số để thay vì nó là Dynamic.com, nó được dịch sang MyBaseUrl / http: //dynamic.com
Jonathan

129

Tôi chỉ muốn thay thế một phần của url và với giải pháp này, tôi không phải chuyển toàn bộ url, chỉ là phần động:

public interface APIService {

  @GET("users/{user_id}/playlists")
  Call<List<Playlist> getUserPlaylists(@Path(value = "user_id", encoded = true) String userId);
}

đã giúp tôi rất nhiều ... Cảm ơn
Siddhesh Shirodkar

32

Bạn có thể sử dụng cờ được mã hóa trên @Pathchú thích:

public interface APIService {
  @GET("{fullUrl}")
  Call<Users> getUsers(@Path(value = "fullUrl", encoded = true) String fullUrl);
}
  • Điều này sẽ ngăn chặn việc thay thế /bằng %2F.
  • Tuy nhiên, nó sẽ không cứu bạn khỏi ?bị thay thế bởi %3Fvì vậy bạn vẫn không thể vượt qua trong chuỗi truy vấn động.

Nó không phải là một lỗi đánh máy.
Matthew Bahr

và phải làm gì để thay thế% 3F bằng?
Yogesh Seralia

19

Kể từ Retrofit 2.0.0-beta2, nếu bạn có dịch vụ phản hồi JSON từ URL này: http: // myhost / mypath

Sau đây không hoạt động:

public interface ClientService {
    @GET("")
    Call<List<Client>> getClientList();
}

Retrofit retrofit = new Retrofit.Builder()
    .baseUrl("http://myhost/mypath")
    .addConverterFactory(GsonConverterFactory.create())
    .build();

ClientService service = retrofit.create(ClientService.class);

Response<List<Client>> response = service.getClientList().execute();

Nhưng điều này là ổn:

public interface ClientService {
    @GET
    Call<List<Client>> getClientList(@Url String anEmptyString);
}

Retrofit retrofit = new Retrofit.Builder()
    .baseUrl("http://myhost/mypath")
    .addConverterFactory(GsonConverterFactory.create())
    .build();

ClientService service = retrofit.create(ClientService.class);

Response<List<Client>> response = service.getClientList("").execute();


3

Bước 1

  Please define a method in Api interface like:-
 @FormUrlEncoded
 @POST()
 Call<RootLoginModel> getForgotPassword(
        @Url String apiname,
        @Field(ParameterConstants.email_id) String username
 );

Bước 2 Để thực hành tốt nhất, hãy xác định một lớp cho trường hợp trang bị thêm: -

  public class ApiRequest {
       static Retrofit retrofit = null;



public static Retrofit getClient() {
    HttpLoggingInterceptor logging = new HttpLoggingInterceptor();
    logging.setLevel(HttpLoggingInterceptor.Level.BODY);

    OkHttpClient okHttpClient = new OkHttpClient().newBuilder()
            .addInterceptor(logging)
            .connectTimeout(60, TimeUnit.SECONDS)
            .readTimeout(60, TimeUnit.SECONDS)
            .writeTimeout(60, TimeUnit.SECONDS)
            .build();

    if (retrofit==null) {
        retrofit = new Retrofit.Builder()
                .baseUrl(URLConstants.base_url)
                .client(okHttpClient)
                .addConverterFactory(GsonConverterFactory.create())
                .build();
    }
    return retrofit;
}

} Bước 3 xác định trong hoạt động của bạn: -

  final APIService request =ApiRequest.getClient().create(APIService.class);
  Call<RootLoginModel> call = request.getForgotPassword("dynamic api 
  name",strEmailid);

2

Thư viện RetrofitHelper được viết bằng kotlin, sẽ cho phép bạn thực hiện các cuộc gọi API, sử dụng một vài dòng mã và bạn có thể sử dụng các URL, Tiêu đề và Params khác nhau , trong mỗi Cuộc gọi.

Thêm nhiều URL trong lớp ứng dụng của bạn như thế này:

class Application : Application() {

    override fun onCreate() {
    super.onCreate()

        retrofitClient = RetrofitClient.instance
                    //api url
                .setBaseUrl("https://reqres.in/")
                    //you can set multiple urls
        //                .setUrl("example","http://ngrok.io/api/")
                    //set timeouts
                .setConnectionTimeout(4)
                .setReadingTimeout(15)
                    //enable cache
                .enableCaching(this)
                    //add Headers
                .addHeader("Content-Type", "application/json")
                .addHeader("client", "android")
                .addHeader("language", Locale.getDefault().language)
                .addHeader("os", android.os.Build.VERSION.RELEASE)
            }

        companion object {
        lateinit var retrofitClient: RetrofitClient

        }
    }  

Và sau đó sử dụng URL bạn cần trong cuộc gọi của bạn:

retrofitClient.Get<GetResponseModel>()
            //set base url
            .setBaseUrlKey("example")
            //set path
            .setPath("api/users/2")
            //set url params Key-Value or HashMap
            .setUrlParams("KEY","Value")
            .setResponseHandler(GetResponseModel::class.java,
                object : ResponseHandler<GetResponseModel>() {
                    override fun onSuccess(response: Response<GetResponseModel>) {
                        super.onSuccess(response)
                        //handle response
                    }
                }).run(this)

Để biết thêm thông tin xem tài liệu


2

URL động với phương thức Nhận và Đăng trong Retrofit (MVVM)

Giao diện dịch vụ trang bị thêm:

public interface NetworkAPIServices {

@POST()
Observable<JsonElement> executXYZServiceAPI(@Url String url,@Body AuthTokenRequestModel param);


@GET
Observable<JsonElement> executeInserInfo(@Url String url);

Lớp dịch vụ MVVM:

   public Observable<JsonElement> executXYZServiceAPI(ModelObject object) {
    return networkAPIServices.authenticateAPI("url",
            object);
}

 public Observable<JsonElement> executeInserInfo(String ID) {
    return networkAPIServices.getBank(DynamicAPIPath.mergeUrlPath("url"+ID)));
}

và lớp khách hàng trang bị thêm

 @Provides
@Singleton
@Inject
@Named("provideRetrofit2")
Retrofit provideRetrofit(@Named("provideRetrofit2") Gson gson, @Named("provideRetrofit2") OkHttpClient okHttpClient) {


   builder = new Retrofit.Builder();
    if (BaseApplication.getInstance().getApplicationMode() == ApplicationMode.DEVELOPMENT) {
        builder.baseUrl(NetworkURLs.BASE_URL_UAT);
    } else {
        builder.baseUrl(NetworkURLs.BASE_URL_PRODUCTION);
    }


    builder.addCallAdapterFactory(RxJava2CallAdapterFactory.create());
    builder.client(okHttpClient);
    builder.addConverterFactory(GsonConverterFactory.create(gson));


    return builder.build();
}

ví dụ: Đây là url: https://gethelp.wildapricot.com/en/articles/549-changing-your

cơ sở: https://gethelp.wildapricot.com

Còn lại @Url: / en / article / 549-change-your (mà bạn vượt qua trong lớp dịch vụ retro)


0
step -*1 

movie_list_row.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="?android:attr/selectableItemBackground"
    android:clickable="true"
    android:focusable="true"

    android:orientation="horizontal"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/row_padding_vertical"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingBottom="@dimen/row_padding_vertical">

    <ImageView
        android:id="@+id/ivImage"
        android:layout_width="60dp"
        android:layout_height="60dp"
        android:layout_marginRight="10dp"
        android:src="@mipmap/ic_launcher" />

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:orientation="vertical">

        <TextView
            android:id="@+id/title"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_alignParentTop="true"
            android:text="Hello"
            android:textColor="@color/title"
            android:textSize="16dp"
            android:textStyle="bold" />

        <TextView
            android:id="@+id/genre"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_below="@id/title"
            android:text="realName" />
    </LinearLayout>

    <TextView
        android:id="@+id/year"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentRight="true"
        android:text="Team"
        android:textColor="@color/year" />

</LinearLayout>                                                                                                            

Api.java                                                                                  
import org.json.JSONObject;

import java.util.List;

import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.http.Field;
import retrofit2.http.FormUrlEncoded;
import retrofit2.http.GET;
import retrofit2.http.POST;

public interface  Api {

    String BASE_URL = "https://simplifiedcoding.net/demos/";

    @GET("marvel")
    Call<List<Hero>> getHeroes();

    @FormUrlEncoded
    @POST("/login")
    public void login(@Field("username") String username, @Field("password") String password, Callback<List<Hero>> callback);

}


MoviesAdapter.java                                                                                       import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;

import com.squareup.picasso.Picasso;

import java.util.List;

public class MoviesAdapter extends RecyclerView.Adapter<MoviesAdapter.MyViewHolder> {

    private List<Hero> moviesList;

    Context context;


    public class MyViewHolder extends RecyclerView.ViewHolder {
        public TextView title, year, genre;
        public ImageView ivImage;

        public MyViewHolder(View view) {
            super(view);
            title = (TextView) view.findViewById(R.id.title);
            genre = (TextView) view.findViewById(R.id.genre);
            year = (TextView) view.findViewById(R.id.year);
            ivImage =  view.findViewById(R.id.ivImage);
            ivImage.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {

                    Toast.makeText(context, "-" + moviesList.get(getAdapterPosition()).getName(), Toast.LENGTH_SHORT).show();
                }
            });
        }
    }


    public MoviesAdapter(List<Hero> moviesList,Context context) {
        this.moviesList = moviesList;
        this.context = context;
    }

    @Override
    public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View itemView = LayoutInflater.from(parent.getContext())
                .inflate(R.layout.movie_list_row, parent, false);

        return new MyViewHolder(itemView);
    }

    @Override
    public void onBindViewHolder(MyViewHolder holder, int position) {
        Hero movie = moviesList.get(position);
        holder.title.setText(movie.getName());
        holder.genre.setText(movie.getRealname());
        holder.year.setText(movie.getTeam());

        Picasso.get().load("http://i.imgur.com/DvpvklR.png").into(holder.ivImage);
    }

    @Override
    public int getItemCount() {
        return moviesList.size();
    }
}                                                                                                                                                        main activity                                                                                                               import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.DefaultItemAnimator;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.Toast;

import java.util.ArrayList;
import java.util.List;

import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;

public class MainActivity extends AppCompatActivity {

    private List<Hero> movieList = new ArrayList<>();
    private RecyclerView recyclerView;
    private MoviesAdapter mAdapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        recyclerView=findViewById(R.id.recycler_view);
        mAdapter = new MoviesAdapter(movieList,MainActivity.this);
        RecyclerView.LayoutManager mLayoutManager = new LinearLayoutManager(getApplicationContext());
        recyclerView.setLayoutManager(mLayoutManager);
        recyclerView.setItemAnimator(new DefaultItemAnimator());
        recyclerView.setAdapter(mAdapter);
        //calling the method to display the heroes
        getHeroes();

    }


    private void getHeroes() {
        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(ApiInterface.BASE_URL)
                .addConverterFactory(GsonConverterFactory.create()) //Here we are using the GsonConverterFactory to directly convert json data to object
                .build();

        ApiInterface api = retrofit.create(ApiInterface.class);

        Call<List<Hero>> call = api.getHeroes();

        call.enqueue(new Callback<List<Hero>>() {
            @Override
            public void onResponse(Call<List<Hero>> call, Response<List<Hero>> response) {
                List<Hero> heroList = response.body();

                //Creating an String array for the ListView
                String[] heroes = new String[heroList.size()];

                //looping through all the heroes and inserting the names inside the string array
                for (int i = 0; i < heroList.size(); i++) {
                    //heroes[i] = heroList.get(i).getName();
                    movieList.add(new Hero( heroList.get(i).getName(), heroList.get(i).getRealname(), heroList.get(i).getTeam()));
                }
                mAdapter.notifyDataSetChanged();

            }

            @Override
            public void onFailure(Call<List<Hero>> call, Throwable t) {
                Toast.makeText(getApplicationContext(), t.getMessage(), Toast.LENGTH_SHORT).show();
            }
        });
    }

}
Hero.java
package com.example.owner.apipractice;
public class Hero {

    private String name;
    private String realname;
    private String team;

    public Hero(String name, String realname, String team) {
        this.name = name;
        this.realname = realname;
        this.team = team;
    }

    private String firstappearance;
    private String createdby;
    private String publisher;
    private String imageurl;
    private String bio;


    public Hero(String name, String realname, String team, String firstappearance, String createdby, String publisher, String imageurl, String bio) {
        this.name = name;
        this.realname = realname;
        this.team = team;
        this.firstappearance = firstappearance;
        this.createdby = createdby;
        this.publisher = publisher;
        this.imageurl = imageurl;
        this.bio = bio;
    }

    public String getName() {
        return name;
    }

    public String getRealname() {
        return realname;
    }

    public String getTeam() {
        return team;
    }

    public String getFirstappearance() {
        return firstappearance;
    }

    public String getCreatedby() {
        return createdby;
    }

    public String getPublisher() {
        return publisher;
    }

    public String getImageurl() {
        return imageurl;
    }

    public String getBio() {
        return bio;
    }
}

0

Nếu bạn đã thiết lập mã và bạn không muốn thay đổi trên các giao diện khác nhau bạn có thể, hãy sử dụng giải pháp được mô tả trong liên kết này . Điểm chính là phương pháp changeApiBaseUrlcập nhật URL và tạo lại trình xây dựng Retrofit.

public class ServiceGenerator {  
public static String apiBaseUrl = "http://futurestud.io/api";
private static Retrofit retrofit;

private static Retrofit.Builder builder =
        new Retrofit.Builder()
                .addConverterFactory(GsonConverterFactory.create())
                .baseUrl(apiBaseUrl);

private static OkHttpClient.Builder httpClient =
        new OkHttpClient.Builder();

// No need to instantiate this class.
private ServiceGenerator() {
}

public static void changeApiBaseUrl(String newApiBaseUrl) {
    apiBaseUrl = newApiBaseUrl;

    builder = new Retrofit.Builder()
                    .addConverterFactory(GsonConverterFactory.create())
                    .baseUrl(apiBaseUrl);
}

public static <S> S createService(Class<S> serviceClass, AccessToken token) {
    String authToken = token.getTokenType().concat(token.getAccessToken());
    return createService(serviceClass, authToken);
}

// more methods
// ...
}

Bạn có thể sử dụng nó như sau:

public class DynamicBaseUrlActivity extends AppCompatActivity {

public static final String TAG = "CallInstances";
private Callback<ResponseBody> downloadCallback;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_file_upload);

    downloadCallback = new Callback<ResponseBody>() {
        @Override
        public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
            Log.d(TAG, "server contacted at: " + call.request().url());
        }

        @Override
        public void onFailure(Call<ResponseBody> call, Throwable t) {
            Log.d(TAG, "call failed against the url: " + call.request().url());
        }
    };

    // first request
    FileDownloadService downloadService = ServiceGenerator.create(FileDownloadService.class);
    Call<ResponseBody> originalCall = downloadService.downloadFileWithFixedUrl();
    originalCall.enqueue(downloadCallback);

    // change base url
    ServiceGenerator.changeApiBaseUrl("http://development.futurestud.io/api");

    // new request against new base url
    FileDownloadService newDownloadService = ServiceGenerator.create(FileDownloadService.class);
    Call<ResponseBody> newCall = newDownloadService.downloadFileWithFixedUrl();
    newCall.enqueue(downloadCallback);
    }
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.