【问题标题】:OkHttp Interceptor using OkHttpClient without dependency cycleOkHttp拦截器使用没有依赖循环的OkHttpClient
【发布时间】:2016-02-11 12:03:48
【问题描述】:

我正在使用 Retrofit 和 Dagger 2。我已经实现了一个 OkHttp Interceptor 来添加 oauth 令牌。如果没有 oauth 令牌或时间戳无效,我会在执行实际请求之前请求一个新令牌(通过 Retrofit 服务)。

这会创建一个依赖循环,其中 Retrofit 服务需要 InterceptorInterceptor 也需要 Retrofit 服务(用于检索 oauth 令牌)。

Interceptor 的示例(为简化起见,它总是通过 restService#refreshAccessToken 请求令牌):

@Override
public Response intercept(Chain chain) throws IOException {
    Request originalRequest = chain.request();
    Request.Builder requestBuilder = originalRequest.newBuilder();

    String authHeader = "Bearer " + restService.refreshAccessToken();
    requestBuilder.addHeader("Authorization", authHeader);
    return chain.proceed(requestBuilder.build());
}

【问题讨论】:

    标签: android dependency-injection retrofit okhttp dagger-2


    【解决方案1】:

    您的Interceptor 需要在Interceptor#intercept() 方法中注入自己。这样,您的 Retrofit 服务(包括添加了拦截器的 OkHttpClient)依赖项就可以在没有依赖循环的情况下得到满足。

    我的NetworkComponent(提供我的改造服务)住在我的Application 班级。这是一个使用应用程序Context 注入它的示例。

    public class AuthInterceptor implements Interceptor {
    
        @Inject RestService restService;
    
        public AuthInterceptor(Context context) {
            mContext = context;
        }
    
        @Override
        public Response intercept(Chain chain) throws IOException {
            // Inject Retrofit service
            ((MyApplication) context.getApplicationContext())
                    .getNetworkComponent().inject(this);
    
            Request originalRequest = chain.request();
            Request.Builder requestBuilder = originalRequest.newBuilder();
    
            String authHeader = "Bearer " + restService.refreshAccessToken();
            requestBuilder.addHeader("Authorization", authHeader);
            return chain.proceed(requestBuilder.build());
        }
    }
    

    你也可以只设置一个局部变量而不注入整个类,可能会获得更好的性能。

    RestService restService = InjectHelper.getNetworkComponent(mContext).restService();
    

    【讨论】:

    • 有趣的方法。是否存在缺点(例如:性能),因为每个请求/拦截都会导致注入?此外,应用程序必须公开 NetworkComponent,这对我来说似乎有点奇怪。
    • Dagger 2 的构建速度很快,因为它只使用生成的代码,所以它本质上只是调用一些设置你的RestService 的方法。我添加了一种替代方法,以避免将整个课程注入我的答案。它不必是Application 提供它,但还有什么可以为您的应用程序提供Singleton 组件?在我读过的所有 Dagger 2 资料中,将应用程序范围的组件存储在 Application 中是常见的做法。
    【解决方案2】:

    我个人更喜欢Lazy injection,更干净一些

    public class AuthInterceptor implements Interceptor {
    
        Lazy<RestService> restService;
    
        @Inject
        public AuthInterceptor(Lazy<RestService> restService) {
            this.restService = restService;
        }
    
        @Override
        public Response intercept(Chain chain) throws IOException {
            Request originalRequest = chain.request();
            Request.Builder requestBuilder = originalRequest.newBuilder();
    
            String authHeader = "Bearer " + restService.get().refreshAccessToken();
            requestBuilder.addHeader("Authorization", authHeader);
            return chain.proceed(requestBuilder.build());
        }
    }
    

    【讨论】:

    • 哇,好干净!这还需要@Inject 注释吗?
    • 这取决于你。如果您编写提供程序,则否
    猜你喜欢
    • 2022-01-13
    • 2016-04-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-10-05
    • 2021-07-13
    • 1970-01-01
    相关资源
    最近更新 更多