首页 > 解决方案 > 刷新令牌时Dagger 2获取旧令牌

问题描述

我遇到了 dagger 2 的问题。简而言之,dagger 2 在我的片段中进行注入,并且令牌是否已过期。TokenAuthenticator 请求保存在 SharedPreferences 中的新令牌。

我的片段没有重新创建,并且 dagger 2 使用过期令牌而不是新令牌进行调用。

现在我将详细解释。

匕首 2

我的匕首 2 逻辑是微不足道的。

网络模块.java

@Provides
@Nullable
String provideAuthToken(Context context) {
    return AccountUtils.getCurrentUserToken(context);
}

@Provides
AuthenticationInterceptor provideInterceptor(@Nullable String authToken) {
    return new AuthenticationInterceptor(authToken);
}

@Provides
TokenAuthenticator provideAuthenticator(Context context, @Nullable String authToken) {
    return new TokenAuthenticator(context, authToken);
}

@Provides
OkHttpClient.Builder provideOkHttpClientBuilder(AuthenticationInterceptor interceptor, TokenAuthenticator authenticator) {
    OkHttpClient.Builder okHttpClientBuilder = new OkHttpClient.Builder();
    okHttpClientBuilder.connectTimeout(15, TimeUnit.SECONDS);
    okHttpClientBuilder.readTimeout(15, TimeUnit.SECONDS);
    okHttpClientBuilder.writeTimeout(15, TimeUnit.SECONDS);
    if (!okHttpClientBuilder.interceptors().contains(interceptor)) {
        okHttpClientBuilder.addInterceptor(interceptor);
        okHttpClientBuilder.authenticator(authenticator);
    }
    return okHttpClientBuilder;
}

它从中获取令牌SharedPreferences并进行改造以调用 API。

改造电话

然后我对 API 做了一个简单的调用(它是一个带有授权令牌的 GET)

ProfileFragment.java

@Inject
ViewModelFactory viewModelFactory;
UserViewModel userViewModel;

@Override
public void onAttach(Context context) {
    ((BaseApplication) context.getApplicationContext())
            .getAppComponent()
            .inject(this);
    super.onAttach(context);
}

@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
    View view = inflater.inflate(R.layout.fragment_profile, container, false);
    ...
    userViewModel = ViewModelProviders.of(this, viewModelFactory).get(UserViewModel.class);
    userViewModel.getUserInfoMutableLiveData().observe(this, this::consumeResponse);
    ...
}

private void consumeResponse(UserResponse userResponse) {
    switch (userResponse.status) {
        case LOADING:
            showProgressBar();
            break;
        case SUCCESS:
            handleSuccessResponse(userResponse.data);
            break;
        case ERROR:
            dismissAll();
            if (getActivity() != null) {
                ResponseHelper.handleErrorResponse(getActivity(), userResponse.error,
                        mContainer, mMainContainer, this);
            }
            break;
    }
}

刷新令牌

现在让我解释会发生什么。

ProfileFragment 被创建,dagger 2 使用注入通过获取保存在SharedPreferences.

ProfileFragment 调用 API,由于令牌已过期,它得到 401 错误代码。

调用 TokenAuthenticatior 刷新令牌,它成功刷新令牌并将NEW令牌保存在SharedPreferences.

再次调用用户信息,但是,由于 ProfileFragment 没有重新创建,它使用具有旧令牌的相同依赖注入进行调用。它使用旧令牌调用 API,然后我们收到错误 401。

如果我现在离开此页面并返回它可以正常工作,因为它会再次进行依赖注入并获取保存在SharedPreferences.

解决方案

  1. 这就是为什么我在考虑一些可以再次注射的方法。例如,重新创建配置文件片段,但我认为这不是一个好主意。在使用匕首 2 之前,我对此没有任何问题。

希望有人会提供帮助。谢谢!

标签: androiddagger-2

解决方案


注入在当前作用域生命周期内发生变化的东西通常是一个坏主意,因为你不能只是再次注入一些东西。正如您所指出的,一旦令牌变得无效,您就必须重新创建整个组件,在这种情况下还强制您重新创建片段。

更好的方法是让你依赖,TokenAuthenticator然后他们可以根据需要读取和更新令牌。无需将 401 传播给用户,因为您可以在 Authenticator 中静默刷新令牌。AuthenticationInterceptorAccountUtils


推荐阅读