Retrofit 2.0多个拦截器

4

我正在使用Retrofit,需要能够使用多个拦截器。目前我正在使用一个自动附加身份验证令牌的拦截器,但我需要能够在没有身份验证令牌的情况下发出调用。如果我添加另一个拦截器并在标头中不使用身份验证令牌,那么我该如何使用该拦截器而不是身份验证令牌拦截器。

    val interceptor: Interceptor = Interceptor { chain ->
    val newRequest = chain.request().newBuilder().
            addHeader("Auth_Token", pref.getString(PSPreferences.prefAuthKey, "")).
            cacheControl(CacheControl.FORCE_NETWORK).
            build()
    chain.proceed(newRequest)
}

okHttpClient = OkHttpClient.Builder().
        readTimeout(1, TimeUnit.MINUTES).
        connectTimeout(1, TimeUnit.MINUTES).
        addInterceptor(interceptor).build()

val retrofitInstance = Retrofit.Builder()
        .baseUrl(APIEndpointInterface.BASE_URL)
        .client(okHttpClient)
        .addConverterFactory(GsonConverterFactory.create())
        .build()
apiInterface = retrofitInstance.create<APIEndpointInterface>(APIEndpointInterface::class.java)

嘿,你最终解决了这个问题吗?我也在寻找完全相同的东西。 - MikeOscarEcho
1个回答

7

OkHttpClient维护着一份拦截器列表,你可以访问它,但这是一个不可修改的集合。

我认为我们有三个选择:

  1. 创建两个OkHttpClient实例,和由此推导出的两个Retrofit实例:一个用于未经身份验证的请求,另一个用于已经通过身份验证的请求。

  2. 检查是否应该使用拦截器,例如在你的身份验证拦截器中,你可以首先检查你的首选项中是否存在令牌密钥,如果有,则使用它;如果没有,则不进行任何修改。你也可以对未经身份验证的拦截器进行同样的操作。我认为这是你的情况下最简单的解决方案。

  3. 创建一个单一的拦截器,它将维护一个可修改的拦截器列表,你可以随意添加和删除拦截器。你需要保留对这个拦截器的引用,可能要将其作为单例模式。

对于第三个选项,我提供了一个非常简单的示例:

public class HttpRequestResponseInterceptor implements Interceptor {

    public final List<RequestInterceptor> requestInterceptors = new ArrayList<>();
    public final List<ResponseInterceptor> responseInterceptors = new ArrayList<>();

    @Override
    public Response intercept(Chain chain) throws IOException {

        Request request = chain.request();

        for (RequestInterceptor interceptor : requestInterceptors) {
            request = interceptor.intercept(request);
        }

        Response response = chain.proceed(request);

        for (ResponseInterceptor interceptor : responseInterceptors) {
            response = interceptor.intercept(response);
        }

        return response;
    }

    public interface RequestInterceptor {
        Request intercept(Request request) throws IOException;
    }

    public interface ResponseInterceptor {
        Response intercept(Response response) throws IOException;
    }
}

在这种情况下,您需要实现自定义接口RequestInterceptorResponseInterceptor
下面是这些接口的一个实现示例:
public class ExampleInterceptor implements HttpRequestResponseInterceptor.RequestInterceptor,
 HttpRequestResponseInterceptor.ResponseInterceptor {

    @Override
    public Request intercept(Request request) throws IOException {
        return request.newBuilder().addHeader("REQUEST_HEADER", "EXAMPLE").build();
    }

    @Override
    public Response intercept(Response response) throws IOException {
        return response.newBuilder().addHeader("RESPONSE_HEADER", "EXAMPLE").build();
    }
}

接下来,您需要将此拦截器两次添加到我们的主要拦截器中,一次添加到requestInterceptors,一次添加到responseInterceptors(如果只拦截请求或只拦截响应,则只需添加到其中一个)。

这个例子远非完整。这种解决方案的好处在于它增加了添加和删除拦截器的能力,而无需重新创建OkHttpClient实例。如果您想支持重试请求等功能,则需要额外的工作。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接