You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.30 08:25:08