在拦截器中调用带Flow的DataStore方法不生效,正确实现方式是什么?
问题原因
你的代码核心问题出在Flow的collect操作符使用上:collect是Flow的永久挂起型终端操作,一旦调用就会持续监听Flow的后续值发射,除非Flow主动结束或者当前协程被取消,所以你的代码会卡在collect调用位置,永远执行不到后续的请求发送逻辑。
正确实现方式
拦截器场景下你只需要获取当前存储的最新一次token值即可,不需要持续监听token变化,直接使用Flow的first()操作符,获取到第一个值后会自动结束订阅,不会产生持续挂起的问题:
class AuthorizationInterceptor @Inject constructor( @ApplicationContext private val appContext: Context, ) : HttpInterceptor { private val authPreferences = AuthPreferences(appContext) override suspend fun intercept( request: HttpRequest, chain: HttpInterceptorChain ): HttpResponse { // 读取当前最新的token值,读取完成后自动终止Flow订阅 val tokenString = authPreferences.getAccessToken.first() return chain.proceed(request.withHeader("Authorization", "Bearer $tokenString")) } }
补充说明
first()本身是suspend函数,刚好适配你当前拦截器suspend intercept的协程环境,读取操作执行完成后立即返回,不会占用额外资源。- 如果你后续需要适配不支持协程的OkHttp原生拦截器,没有suspend修饰的intercept方法,可以用
runBlocking { authPreferences.getAccessToken.first() }同步获取token,DataStore本地读取速度极快,不会造成主线程卡顿。 - 可以增加token为空的判断逻辑,针对需要授权的请求直接返回401状态,或者触发全局登录跳转逻辑,避免无效请求发送到服务端。
内容的提问来源于stack exchange,提问作者BeGo
相关产品推荐
相关产品推荐

