kotlin 如何在okhttp拦截器中使用jectpack数据存储?它需要一个上下文对象

68bkxrlz  于 2023-02-19  发布在  Kotlin
关注(0)|答案(3)|浏览(148)

我想在拦截器中添加一个令牌到请求头。但是现在我不知道该怎么做。
这是我数据存储

val Context.dataStore: DataStore<Preferences> by preferencesDataStore(name = "settings")

class SettingsManager(context: Context) {
    private val dataStore = context.dataStore

    val getToken = dataStore.data
        .catch {
            if (it is IOException) {
                it.printStackTrace()
                emit(emptyPreferences())
            } else {
                throw it
            }
        }.map { preference ->
            preference[token] ?: ""
        }

    suspend fun setToken(tokenStr: String) {
        dataStore.edit { preferences ->
            preferences[token] = tokenStr
        }
    }

    companion object {
        val token = stringPreferencesKey("token")
    }
}

我无法在Interceptor中获取上下文对象。
所以我试着用刀柄来固定它

class RequestInterceptor(private val settingsManager: SettingsManager) : Interceptor {

    override fun intercept(chain: Interceptor.Chain): Response {
        val request = chain.request()
        runBlocking {
            val first = settingsManager.getToken.first()
            LogUtil.i("token " + first)
            request.newBuilder().addHeader("token", first).build();
        }
        return chain.proceed(request)
    }
}

我不知道下一步@AndroidEntryPoint不能在拦截器类上使用。
请各位给予我一些解决办法

yzckvree

yzckvree1#

我只是用这种方式。

suspend fun getToken() : String? {
    val preference = dataStore.data.first()
    return preference[PREF_JWT_TOKEN]
} // this is inside the datastore local repository.

在拦截器内部,您可以获得如下runBlocking UI。

val builder = Retrofit.Builder()
        .baseUrl(Constants.BASE_URL)
        .addConverterFactory(GsonConverterFactory.create())
    val client = OkHttpClient.Builder()
        .addInterceptor { chain ->
            val original = chain.request()
            var token: String? = null
            runBlocking {
                token = dataStorePreferenceRepository.getToken()
                if (!token.isNullOrEmpty()) {
                    val authorized = original.newBuilder()
                        .addHeader("Authorization", "Bearer $token")
                        .build()
                    chain.proceed(authorized)
                } else {
                    chain.proceed(original)
                }
            }
        }.addNetworkInterceptor(StethoInterceptor()).build()
    return builder.client(client).build().create(ApiInterface::class.java)

在Module类中,像这样使用。

@Module                                                                                                            
@InstallIn(SingletonComponent::class)                                                                              
object AppModule {                                                                                                 
                                                                                                                   
                                                                                                                   
    @Provides                                                                                                      
    @Singleton                                                                                                     
    fun getDataStorePreferenceRepository(@ApplicationContext appContext: Context): DataStorePreferenceRepository { 
        return DataStorePreferenceRepository(context = appContext)                                                 
    }                                                                                                              
                                                                                                               }
kknvjkwl

kknvjkwl2#

如果您只是将@Inject constructor添加到RequestInterceptor中,您应该能够在Hilt中看到它。
例如
class RequestInterceptor @Inject constructor(private val settingsManager: SettingsManager) : Interceptor {...
我不确定您是否可以像这样使用SettingsManager,但您可以尝试使用class SettingsManager @Inject constructor(@ApplicationContext context: Context) {

kmbjn2e3

kmbjn2e33#

这对我有用

override fun intercept(chain: Interceptor.Chain): Response {
    return runBlocking {
        val token = dataStorePreferences.getAuthToken().first()
        val request = chain.request().newBuilder().addHeader(AUTHORIZATION_HEADER, "$BEARER $token").build()
        val response = chain.proceed(request)
        if (response.code == UNAUTHORIZED_CODE) {
            try {
                dataStorePreferences.setAuthToken(token)
                chain.proceed(request.newBuilder().addHeader(AUTHORIZATION_HEADER, "$BEARER $token").build())
            } catch (exeption: Exception) {
                dataStorePreferences.setAuthToken("")
                response
            }
        } else {
            response
        }
    }
}

相关问题