Android 匕首2当令牌刷新时获得旧令牌

Android 匕首2当令牌刷新时获得旧令牌,android,dagger-2,Android,Dagger 2,我的匕首2有问题。简单地说,匕首2在我的碎片中进行注射,如果令牌过期。TokenAuthenticator请求保存在SharedReferences中的新令牌 我的碎片没有被重新创建,匕首2使用过期的令牌而不是新的令牌进行调用 现在我将详细解释 匕首2 我的匕首2逻辑是微不足道的 NetworkModule.java 它从SharedReferences获取令牌,并进行改装以调用API 改装呼叫 然后我对API进行一个简单的调用,它是一个带有授权令牌的GET ProfileFragment.ja

我的匕首2有问题。简单地说,匕首2在我的碎片中进行注射,如果令牌过期。TokenAuthenticator请求保存在SharedReferences中的新令牌

我的碎片没有被重新创建,匕首2使用过期的令牌而不是新的令牌进行调用

现在我将详细解释

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

NetworkModule.java

它从SharedReferences获取令牌,并进行改装以调用API

改装呼叫 然后我对API进行一个简单的调用,它是一个带有授权令牌的GET

ProfileFragment.java

刷新令牌 现在让我解释一下发生了什么

ProfileFragment创建后,dagger 2使用注入来通过获取保存在SharedReferences中的令牌来创建组件

ProfileFragment调用API时,会得到401个错误代码,因为令牌已过期

调用TokenAuthenticationor刷新令牌,它成功刷新令牌并将新令牌保存在SharedReferences中

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

如果我现在离开这个页面,然后回来,它工作得很好,因为它再次执行依赖项注入,并获得保存在SharedReferences中的新令牌

解决 这就是为什么我在想办法让注射再次成功。例如,重新创建概要文件片段,但我认为这不是一个好主意。在使用匕首2之前,我没有任何问题。
希望有人能帮忙。谢谢

注入在当前作用域生命周期内发生变化的内容通常是个坏主意,因为您不能再注入内容。一旦令牌变得无效,您就必须重新创建整个组件,在本例中,正如您所指出的,这也迫使您重新创建片段


更好的方法是让您的TokenAuthenticator和AuthenticationInterceptor依赖于AccountUtils,然后它们可以根据需要读取和更新令牌。无需将401传播给用户,因为您可以在验证器中以静默方式刷新令牌。

注入在当前作用域生存期内发生变化的内容通常是个坏主意,因为您不能再次注入内容。一旦令牌变得无效,您就必须重新创建整个组件,在本例中,正如您所指出的,这也迫使您重新创建片段


更好的方法是让您的TokenAuthenticator和AuthenticationInterceptor依赖于AccountUtils,然后它们可以根据需要读取和更新令牌。无需将401传播给用户,因为您可以在验证器中以静默方式刷新令牌。

正如@David Medenjak在接受的答案中指出的那样。我确实让我的TokenAuthentication和AuthenticationInterceptor直接依赖于令牌,而不是在NetworkModule中提供令牌

NetworkModule.java

现在,NetworkModule不再有对令牌的任何引用

AuthenticationInterceptor直接引用保存在SharedReferences中的令牌

public AuthenticationInterceptor(Context context) {
    this.context = context;
}

@Override
public Response intercept(@NonNull Chain chain) throws IOException {
    String authToken = AccountUtils.getCurrentUserToken(context);
    Request request = chain.request();
    Request.Builder newRequest;
    if (authToken != null) {
        int index = authToken.lastIndexOf(".");
        newRequest = request.newBuilder().header(Constants.AUTHORIZATION, authToken);
    } else {
        newRequest = request.newBuilder();
    }
    return chain.proceed(newRequest.build());
}

通过这种方式,即使我们使用的是同一个AuthenticationInterceptor实例,它也会在每个请求中请求保存在SharedReferences中的令牌。然后,我们将根据需要成功刷新令牌。

正如@David Medenjak在接受的答案中指出的那样。我确实让我的TokenAuthentication和AuthenticationInterceptor直接依赖于令牌,而不是在NetworkModule中提供令牌

NetworkModule.java

现在,NetworkModule不再有对令牌的任何引用

AuthenticationInterceptor直接引用保存在SharedReferences中的令牌

public AuthenticationInterceptor(Context context) {
    this.context = context;
}

@Override
public Response intercept(@NonNull Chain chain) throws IOException {
    String authToken = AccountUtils.getCurrentUserToken(context);
    Request request = chain.request();
    Request.Builder newRequest;
    if (authToken != null) {
        int index = authToken.lastIndexOf(".");
        newRequest = request.newBuilder().header(Constants.AUTHORIZATION, authToken);
    } else {
        newRequest = request.newBuilder();
    }
    return chain.proceed(newRequest.build());
}

通过这种方式,即使我们使用的是同一个AuthenticationInterceptor实例,它也会在每个请求中请求保存在SharedReferences中的令牌。然后,我们将根据需要成功刷新令牌。

首先,感谢您阅读我的问题。让我看看我是否得到了它,我把TokenAuthenticator和AuthenticationInterceptor从dagger 2逻辑中放出来,然后从NetworkModule中创建?@SoonSantos验证器和其他验证器可以是dagger的一部分,只是不包括@Nullable String authToken,而是直接通过您的AccountUtils访问它,您可以首先读取和写入Token,非常感谢你阅读我的问题。让我看看我是否得到了它,我把TokenAuthenticator和AuthenticationInterceptor从dagger 2逻辑中放出来,然后从NetworkModule中创建?@SoonSantos验证器和其他验证器可以是dagger的一部分,只是不包括@Nullable String authToken,但是通过您的AccountUtils直接访问它,您可以在这里读写当天保存的令牌,谢谢!拯救了这一天谢谢!
@Provides
AuthenticationInterceptor provideInterceptor(Context context) {
    return new AuthenticationInterceptor(context);
}

@Provides
TokenAuthenticator provideAuthenticator(Context context) {
    return new TokenAuthenticator(context);
}
public AuthenticationInterceptor(Context context) {
    this.context = context;
}

@Override
public Response intercept(@NonNull Chain chain) throws IOException {
    String authToken = AccountUtils.getCurrentUserToken(context);
    Request request = chain.request();
    Request.Builder newRequest;
    if (authToken != null) {
        int index = authToken.lastIndexOf(".");
        newRequest = request.newBuilder().header(Constants.AUTHORIZATION, authToken);
    } else {
        newRequest = request.newBuilder();
    }
    return chain.proceed(newRequest.build());
}