Jetpack Compose中Retrofit拦截器读取DataStore旧JWT问题
问题原因
你的问题核心在于TokenInterceptor初始化时只读取了一次DataStore的JWT值,之后不会自动更新:
SplitFoolDataContainer中的retrofit和createOkHttpClient都是通过lazy延迟加载的,第一次创建时会读取当时DataStore里的token并传给TokenInterceptor。- 登录后DataStore的token更新了,但
TokenInterceptor里存储的还是初始化时的旧值——因为OkHttpClient和Retrofit实例是单例,不会重新创建。 - 重启应用后,容器重新初始化,会读取最新的token,所以能正常工作。
解决方案
1. 修改TokenInterceptor,每次请求读取最新token
把Interceptor改成每次拦截请求时实时从DataStore获取最新token,而非初始化时一次性传入:
class TokenInterceptor(private val dataStore: DataStore<Preferences>) : Interceptor { private val jwtTokenKey = stringPreferencesKey("is_jwt_token") override fun intercept(chain: Interceptor.Chain): Response { // 每次请求时读取最新的token val latestToken = runBlocking { dataStore.data.map { preferences -> preferences[jwtTokenKey] ?: "" }.first() } val request = chain.request().newBuilder() .addHeader("Authorization", "Bearer $latestToken") .build() return chain.proceed(request) } }
2. 调整OkHttpClient的创建逻辑
不再提前读取token,直接把DataStore传给Interceptor:
private fun createOkHttpClient(): OkHttpClient { val tokenInterceptor = TokenInterceptor(dataStore = context.dataStore) return OkHttpClient.Builder() // 可重新启用Authenticator(用于处理401重试逻辑) .authenticator(AuthAuthenticator(context.dataStore)) .addInterceptor(tokenInterceptor) .build() }
3. 简化AuthAuthenticator(可选)
原Authenticator里的synchronized和重复读取token逻辑冗余,简化后:
class AuthAuthenticator(private val dataStore: DataStore<Preferences>) : Authenticator { private val jwtTokenKey = stringPreferencesKey("is_jwt_token") override fun authenticate(route: Route?, response: Response): Request? { val latestToken = runBlocking { dataStore.data.map { it[jwtTokenKey] ?: "" }.first() } Log.d("AuthAuthenticator", "使用最新token重试请求: $latestToken") return response.request.newBuilder() .header("Authorization", "Bearer $latestToken") .build() } }
关键说明
修改后,每次发起API请求时,Interceptor都会实时读取DataStore中的最新token,登录后更新的token会立即生效,无需重启应用。
内容的提问来源于stack exchange,提问作者Gaurav Roy
相关产品推荐
相关产品推荐

