有没有一种方法来添加查询参数的每个请求与逆转2?

我需要添加一个查询参数的每个请求所提出的逆转2.0。0-beta2库。我发现 这个解决方案的逆转1.9,但如何添加 RequestInterceptor在最新的库版本?

我的界面:

@GET("user/{id}")
Call<User> getUser(@Path("id")long id);


@GET("users/")
Call<List<User>> getUser();

客户:

Retrofit retrofit = new Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.client(CLIENT)  // custom OkHTTP Client
.build();
service = retrofit.create(userService.class);
41059 次浏览

你必须从 OkHttp切换到 Interceptor。创建一个 OkHttpClient,将 Interceptor添加到其中,并将该客户端传递到便于翻新的 Builder中。

OkHttpClient client = new OkHttpClient();
client.interceptors().add(new Interceptor() {
@Override
public Response intercept(Chain chain) throws IOException {
...
}
});


Retrofit retrofit = new Retrofit.Builder()
.baseUrl("...")
.client(client)
.build();

然后您可以使用 chain.request().newBuilder()根据需要调整请求。

为了完整起见,下面是您需要使用 OkHttp-Interceptor 为每个 Revifit 2.x 请求添加一个参数的完整代码:

OkHttpClient client = new OkHttpClient();


client.interceptors().add(new Interceptor() {
@Override
public Response intercept(Chain chain) throws IOException {
Request request = chain.request();
HttpUrl url = request.url().newBuilder().addQueryParameter("name","value").build();
request = request.newBuilder().url(url).build();
return chain.proceed(request);
}
});


Retrofit retrofit = new Retrofit.Builder()
.baseUrl("...")
.client(client)
.build();

现在,改造已经发布了2.0.0版本,这就是我的解决方案:

OkHttpClient client = new OkHttpClient.Builder()
.addInterceptor(new Interceptor() {
@Override
public Response intercept(Chain chain) throws IOException {


String uid = "0";
long timestamp = (int) (Calendar.getInstance().getTimeInMillis() / 1000);
String signature = MD5Util.crypt(timestamp + "" + uid + MD5_SIGN);
String base64encode = signature + ":" + timestamp + ":" + uid;
base64encode = Base64.encodeToString(base64encode.getBytes(), Base64.NO_WRAP | Base64.URL_SAFE);


Request request = chain.request();
HttpUrl url = request.url()
.newBuilder()
.addQueryParameter("pageSize", "2")
.addQueryParameter("method", "getAliasList")
.build();


request = request
.newBuilder()
.addHeader("Authorization", "zui " + base64encode)
.addHeader("from_client", "ZuiDeer")
.url(url)
.build();


Response response = chain.proceed(request);
return response;
}
}).build();




Retrofit retrofit = new Retrofit.Builder()
.baseUrl(ApiConstants.API_BASE_URL)
.client(client)
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.build();


mRestfulService = retrofit.create(RestfulService.class);

3.2.0或更高的版本中,你应该在 OkHttpClient.Builder中使用 addInterceptor()

例如,对于 Retrolambda:

HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor()
.setLevel(HttpLoggingInterceptor.Level.BASIC);


Interceptor clientInterceptor = chain -> {
Request request = chain.request();
HttpUrl url = request.url().newBuilder().addQueryParameter("name", "value").build();
request = request.newBuilder().url(url).build();
return chain.proceed(request);
};


OkHttpClient client = new OkHttpClient.Builder()
.addNetworkInterceptor(clientInterceptor)
.addInterceptor(loggingInterceptor)
.build();


Retrofit retrofit = new Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.client(client)
.build();

很多答案都是相似的,但是我遇到的一个问题是 Interceptor内部的函数链,这导致了它的失败。根据链接视频更改 不能直接进入网址。相反,必须制作 URL 的副本,然后重新分配回原始 URL,如下所示:

{

public method(){
final String api_key = "key";


OkHttpClient client = new OkHttpClient.Builder()
.addInterceptor(new Interceptor() {
@Override
public Response intercept(Chain chain) throws IOException {
Request original = chain.request();
HttpUrl httpUrl = original.url();


HttpUrl newHttpUrl = httpUrl
.newBuilder()
.addQueryParameter("api_key", api_key)
.build();


Request.Builder requestBuilder = original
.newBuilder()
.url(newHttpUrl);


Request request = requestBuilder
.build();
return chain.proceed(request);
}
}).build();




retrofit = new Retrofit.Builder()
.baseUrl("https://base.url.ext/")
.client(client)
.addConverterFactory(GsonConverterFactory.create())
.build();
}

虽然调用的函数与第一个应答相同,但这个应答对函数的调用进行了分区。也就是说,原始 url 和新 url 都存储在单独的局部变量中。这样可以防止覆盖原始 URL,直到您希望 OkHttpClient这样做为止。

在 kotlin 中,将下面的拦截器添加到您设置在 Afterfit 构建器中的 OkHttpClient:

Retrofit.Builder()
.baseUrl("...")
.client(
OkHttpClient.Builder()
.addInterceptor { chain ->
val url = chain
.request()
.url()
.newBuilder()
.addQueryParameter("key", "value")
.build()
chain.proceed(chain.request().newBuilder().url(url).build())
}
.build()
)
.build()
.create(FooService::class.java)

当然,将 OkHttpClient 构建提取到 val 或注入依赖项中将使其更加模块化和易用。

对于清洁代码方法,拦截器链有一个单独的类,如下所示:

    public class LanguageInterceptor implements Interceptor {
@Override
public Response intercept(Chain chain) throws IOException {
HttpUrl url = chain.request()
.url()
.newBuilder()
.addQueryParameter("name","value")
.build();


Request request = chain.request()
.newBuilder()
.url(url)
.build();
Response response = chain.proceed(request);
return response;
}
}

然后在定义改造实例的类中,使用 .addInterceptor(new LanguageInterceptor())向其添加实例对象,如下所示:

public static Retrofit getClient() {
HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
OkHttpClient client = new OkHttpClient.Builder()
.connectTimeout(30, TimeUnit.SECONDS)
.readTimeout(30, TimeUnit.SECONDS)
.addInterceptor(new LanguageInterceptor())
.addInterceptor(interceptor)
.build();


if (retrofit == null) {
retrofit = new Retrofit.Builder()
.baseUrl(BASE_URL)
.client(client)
.addConverterFactory(ScalarsConverterFactory.create())
.addConverterFactory(GsonConverterFactory.create())
.build();
Log.e(TAG, "getClient: base url " + retrofit.baseUrl());
}
return retrofit;
}