android - 访问 token 更新 Dagger 和 Retrofit 时更新请求 header

标签 android retrofit dagger okhttp3

我想在网络请求中更新访问 token 。但是使用 Dagger 和 Retrofit 有一些困难。

😢对不起,我的英文不好,所以给你一个例子可能会很清楚。从头开始,我的想法是这样的:

provide an access token saved in shared preference


@Provides
@ForOauth
Preference<String> provideAccessToken(RxSharedPreferences prefs) {
    return prefs.getString(PrefsUtils.KEY_ACCESS_TOKEN);
}

use access token to create an interceptor and added into okhttp client


@Provides
@Singleton
@Named("Cached")
public OkHttpClient provideOkHttpClientWithCache(Application application, @ForOauth OauthInterceptor oauthInterceptor) {
      ...
    builder.addInterceptor(oauthInterceptor);
      ...
}

and I provide the OauthInterceptor instance by its constructor


@Inject
public OauthInterceptor(@ForOauth Preference<String> accessToken) {
    this.accessToken = accessToken;
    Timber.tag("OauthInterceptor");
}

但是由于 okhttp 客户端是单例的,所以当 prefs 中的访问 token 更新时它不会改变。我认为可能可行的另一种方法是使用自定义范围,如 @ForOauth什么的,但它只是一个粗略的草图......

顺便说一句,我还有一个这样的想法:

get the access token from prefs in the intercept() method , so every time I can have a request header which contains the latest access token.


@Override
public Response intercept(Chain chain) throws IOException {
    Request.Builder builder = chain.request().newBuilder();
    if (accessToken.isSet()) {
        // Preference<String> accessToken
        builder.header("Authorization", ACCESS_TYPE + accessToken.get());
    } else {
        builder.header("Authorization", "Bearer xxxxxx");
    }
    return chain.proceed(builder.build());
}

但是我还没有真正尝试过这个想法,我认为它是不对的😂

我想知道我是否必须每次都创建一个新的 okhttp 客户端实例,或者我可以更新访问 token 然后 okhttp 客户端单例可以刷新它的拦截器......

所以你能给我一些建议,或者一个简单的工作例子。

提前谢谢😊

最佳答案

嗯,我已经这样做了很多次,并且从未注意到访问 token 刷新没有沿着链向下传递到 OkHttp 的任何问题。这是我在应用程序中使用的典型设置:

@Provides @Singleton
SharedPreferences providePreferences(Context ctx) {
    return new SharedPreferences(ctx);
}

@Provides @Singleton
HttpLoggingInterceptor provideLoggingInterceptor(){
    return new HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BODY);
}

@Provides @Singleton
OkHttpClient provideClient(HttpLoggingInterceptor interceptor, SharedPreferences prefs){
    return new OkHttpClient.Builder()
            .addNetworkInterceptor(chain -> {
                // Add Auth Header
                String token = prefs.accessToken().get();
                if(token == null) token = "";

                Request request = chain.request().newBuilder().addHeader("Authorization", token).build();
                return chain.proceed(request);
            })
            .addInterceptor(interceptor)
            .build();
}

@Provides @Singleton
Retrofit provideRetrofit(@ApiUrl String url, OkHttpClient client){
    return new Retrofit.Builder()
            .baseUrl(url)
            .client(client)
            .addConverterFactory(LoganSquareConverterFactory.create())
            .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
            .build();
}
SharedPreferences只是一个类,我抽象了一些 RxSharedPreferences逻辑成。也可以@Inject它也可以在应用程序中的任何需要它的地方使用,这很好。这是该类的一个简单版本,只是为了好玩:
public class SharedPreferences {
    // Constants and variables
    private static final String PREFERENCE_FILENAME = BuildConfig.APPLICATION_ID + ".prefs";
    private static final String PREF_ACCESS_TOKEN= "pref_access_token";

    private RxSharedPreferences mRxSharedPrefs;

    // Constructor
    public SharedPreferences(Context context) {
        mRxSharedPrefs = RxSharedPreferences.create(context.getSharedPreferences(PREFERENCE_FILENAME, Context.MODE_PRIVATE));
    }

    // Helper methods
    public Preference<String> accessToken() { return mRxSharedPrefs.getString(PREF_ACCESS_TOKEN, ""); }

    public void logout() { accessToken().delete(); }
}

关于android - 访问 token 更新 Dagger 和 Retrofit 时更新请求 header ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39136081/

相关文章:

android - 改造 2 : Catch connection timeout exception

Android 使用 Dagger 2 为动态更改 url 实现 HostSelectionInterceptor

java - Retrofit/OkHttp 删除 Transfer-Encoding header

Android xml样式引用属性崩溃

android - 如何在库中使用 android 数据绑定(bind)

android - MediaPlayer getCurrentPosition() 问题

java - ANDROID:MVVM + Retrofit:如何以及在哪里从 JSON 对象数组检索 JSON 对象列表?

android - 我缺少一些 Dagger 基础知识 [CoffeeMaker App 示例]

Android Dagger 依赖循环

Android 2.2 蓝牙问题(采用 BluetoothChat 示例)