#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
, когда это необходимо.
Это один из способов сделать это:
- Измените
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()
)
}
}
- При создании вашего
AuthInteceptor
создайте свой лямбда-код для динамической ссылки наSharedPreferences
@Module
class AppModule {
@Singleton
@Provides
fun provideAuthInterceptor(sharedPreferencesSources: SharedPreferencesSources): Interceptor {
return AuthInterceptor(){ sharedPreferencesSources.tokenApi() }
}
//...
}
Таким образом, tokenProvider
будет invoked
( SharedPreferences
будет доступен) каждый раз, когда вы выполняете вызов api, а не только один раз при создании AuthInterceptor
.