Токен JWT не будет обновляться при использовании dagger 2?

#android #kotlin #dependency-injection #dagger-2 #dagger

#Android #kotlin #внедрение зависимостей #dagger-2 #dagger

Вопрос:

У меня проблема с использованием dagger 2 для обновления токена во время выполнения.

Итак, вот сценарий:

У меня есть экран для смены пароля. когда мне удастся обновить пароль, текущий токен jwt будет недействительным, и мне нужно сохранить новый токен из ответа токена обновления, я сохраняю этот токен в SharedPreferences. но проблема в том, когда я сохраняю токен. он обновлен в sharedprefernces, но не будет обновлять значение в DaggerGraph, где я создаю экземпляр модификации (заголовок авторизации).

Ниже приведен мой код :

AppComponent.kt

 @Singleton
@Component(
    modules = [StorageModule::class, AppModule::class, ViewModelModule::class]
)
interface AppComponent {

    @Component.Factory
    interface Factory {
        fun create(@BindsInstance context: Context): AppComponent
    }

    fun inject(activity: SplashActivity)

    fun inject(activity: LoginActivity)

    fun inject(activity: MainActivity)

    fun inject(activity: ChangePasswordActivity)
}
  

AppModule.kt

 @Module
class AppModule {

    @Singleton
    @Provides
    fun provideAuthInterceptor(sharedPreferencesSources: SharedPreferencesSources): Interceptor {
        return AuthInterceptor(sharedPreferencesSources.tokenApi())
    }

    @Singleton
    @Provides
    fun provideApiService(
        authInterceptor: Interceptor
    ): SharedProductClient {
        return Network.retrofitClient(authInterceptor = authInterceptor)
            .create(SharedProductClient::class.java)
    }

    @Singleton
    @Provides
    fun provideAppRepository(apiService: SharedProductClient): AppRepository {
        return AppRepositoryImpl(apiService)
    }

    @Singleton
    @Provides
    fun provideAppUseCase(appRepository: AppRepository): AppUseCase {
        return AppUseCase(appRepository)
    }
   
    @Singleton
    @Provides
    fun provideAppScheduler(): SchedulerProvider = AppSchedulerProvider()
}
  

StorageModule.kt

 @Module
class StorageModule {

    @Singleton
    @Provides
    fun provideSharedPreferences(context: Context): SharedPreferences {
        return context.getSharedPreferences(SharedPrefName, Context.MODE_PRIVATE)
    }

    @Singleton
    @Provides
    fun provideSharedPreferencesSource(sharedPrefInstance: SharedPreferences): SharedPreferencesSources {
        return SharedPreferencesSourcesImpl(sharedPrefInstance)
    }

    companion object {
        const val SharedPrefName = "share_product_prefs"
    }
}
  

AuthInterceptor.kt

 class AuthInterceptor constructor(
    private val token: String
) : Interceptor {

    override fun intercept(chain: Interceptor.Chain): Response = chain.run {
        proceed(
            request()
                .newBuilder()
                .addHeader("Accept", "application/json")
                .addHeader("Authorization", "Bearer $token")
                .build()
        )
    }
}
  

Любое предложение действительно помогло бы мне. Спасибо!

Комментарии:

1. Можете ли вы указать, где вы пытаетесь переопределить токен в настройках осколка.

2. хай, я поместил sharedpreferennces в интерфейс с его реализацией. и предоставьте его интерфейс в StorageModule.kt

Ответ №1:

Это потому, что вы передаете String экземпляр токена только при создании AuthInterceptor .

Вы должны предоставить способ (например, интерфейс) динамического получения токена из SharedPreferences , когда это необходимо.


Это один из способов сделать это:

  1. Измените token:String тип функции в вашем AuthInterceptor конструкторе (и используйте его при необходимости):
 class AuthInterceptor constructor(
    private val tokenProvider: () -> String
) : Interceptor {

    override fun intercept(chain: Interceptor.Chain): Response = chain.run {
        proceed(
            request()
                .newBuilder()
                .addHeader("Accept", "application/json")
                .addHeader("Authorization", "Bearer ${tokenProvider.invoke()}")
                .build()
        )
    }
}
  
  1. При создании вашего AuthInteceptor создайте свой лямбда-код для динамической ссылки на SharedPreferences
 @Module
class AppModule {

    @Singleton
    @Provides
    fun provideAuthInterceptor(sharedPreferencesSources: SharedPreferencesSources): Interceptor {
        return AuthInterceptor(){ sharedPreferencesSources.tokenApi() }
    }

    //...
}
  

Таким образом, tokenProvider будет invoked ( SharedPreferences будет доступен) каждый раз, когда вы выполняете вызов api, а не только один раз при создании AuthInterceptor .