Java 有没有办法使用 Retrofit 2 向每个请求添加查询参数?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/32948083/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 14:04:20  来源:igfitidea点击:

Is there a way to add query parameter to every request with Retrofit 2?

javaandroidretrofit

提问by Max

I need to add a query parameter to every request made by Retrofit 2.0.0-beta2 library. I found this solutionfor Retrofit 1.9, but how to add RequestInterceptorin newest library version?

我需要为 Retrofit 2.0.0-beta2 库发出的每个请求添加一个查询参数。我为 Retrofit 1.9找到了这个解决方案,但是如何添加RequestInterceptor最新的库版本?

My interface:

我的界面:

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

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

Client:

客户:

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

采纳答案by Lukas Lechner

For the sake of completeness, here is the full code you need to add a parameter to every Retrofit 2.x request using a OkHttp-Interceptor:

为了完整起见,这里是使用 OkHttp-Interceptor 向每个 Retrofit 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();

回答by sebastian

You have to switch to an Interceptorfrom OkHttp. Create an OkHttpClient, add the Interceptorto it an pass that client in the Retrofit Builder.

您必须切换到Interceptorfrom OkHttp。创建一个OkHttpClientInterceptor在 Retrofit 中添加一个传递给它的客户端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();

You can then adjust the request to your needs using chain.request().newBuilder(). See the documentationfor details.

然后,您可以使用 调整请求以满足您的需要chain.request().newBuilder()。有关详细信息,请参阅文档

回答by zenghui.wang

now the Retrofit has release 2.0.0 and this is my solution:

现在 Retrofit 发布了 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);

回答by Sergey Nikitin

In 3.2.0and higher you should use addInterceptor()in OkHttpClient.Builderinstead.

In3.2.0及更高版本,您应该使用addInterceptor()inOkHttpClient.Builder代替。

For example, with Retrolambda:

例如,使用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();

回答by isakbob

A lot of these answers are similar, but an issue I came accross is the chaining of functions inside the Interceptorwhich led it to fail for me. Changes cannot be made directly to a urlaccording to the linked video. Rather, a copy of the url must be made and then reassigned back to the original url as shown below:

这些答案中有很多是相似的,但我遇到的一个问题是里面的函数链接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();
}

While the functions called are identical to the first answer, this answer partitions the function calls out. Namely, the original url as well as the new url are stored in separate local variables. This prevents overwriting the original url until you want the OkHttpClientto do so.

虽然调用的函数与第一个答案相同,但此答案将函数调用分开。即,原始 url 和新 url 存储在单独的局部变量中。这可以防止覆盖原始 url,直到您想OkHttpClient要这样做。

回答by Achraf Amil

In kotlin, add the following interceptor to the OkHttpClient you set in Retrofit builder :

在 kotlin 中,将以下拦截器添加到您在 Retrofit builder 中设置的 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)

And, of course, extracting the OkHttpClient building into a val or an injection dependency would make it even more modular and lisible.

而且,当然,将 OkHttpClient 构建提取到 val 或注入依赖项中会使其更加模块化和可靠。