You need to enable JavaScript to run this app. 使用OkHttp认证时Authenticator如何等待刷新token结果后返回Request
优惠活动
大模型
产品
解决方案
定价
更多

使用OkHttp认证时Authenticator如何等待刷新token结果后返回Request

关于OkHttp Authenticator中同步等待刷新Token结果的解决方案

核心原理

Authenticator的authenticate方法本身由OkHttp在独立的后台工作线程调用,并非UI线程,因此你可以在该方法内执行同步阻塞操作等待Token刷新结果,不会导致界面卡顿。

不同实现方案的正确写法

1. RXJava 版本

你之前的写法问题在于doOnSuccess是异步回调,回调执行时外层authenticate方法已经结束返回,无法将结果返回给外层。直接使用RX提供的同步阻塞方法blockingGet()即可拿到结果:

class TokenAuthenticator : Authenticator {
    override fun authenticate(route: Route?, response: Response): Request? {
        return try {
            // 同步阻塞等待刷新Token接口返回
            val newToken = getTokenFromServer()?.blockingGet()?.result?.token ?: return null
            // 构造携带新Token的请求返回
            response.request.newBuilder()
                .addHeader("token", newToken)
                .build()
        } catch (e: Exception) {
            // 刷新失败,返回null让OkHttp放弃重试
            null
        }
    }

    fun getTokenFromServer(): Single<ApiResponse>? {
        // 原有刷新Token的接口实现
    }
}

2. 协程版本

你第二种协程写法的思路是对的,runBlocking会阻塞当前线程直到内部协程执行完成,刚好符合我们需要同步返回结果的要求:

class TokenAuthenticator : Authenticator {
    override fun authenticate(route: Route?, response: Response): Request? {
        return runBlocking(Dispatchers.IO) {
            try {
                val newToken = getTokenFromServer()?.result?.token ?: return@runBlocking null
                response.request.newBuilder()
                    .addHeader("token", newToken)
                    .build()
            } catch (e: Exception) {
                null
            }
        }
    }

    // 注意这里getTokenFromServer要改成suspend挂起函数的实现
    suspend fun getTokenFromServer(): ApiResponse? {
        // 协程版本的刷新Token接口实现
    }
}

你的疑问解答

  • 关于RX无法在doOnSuccess返回Request:doOnSuccess是异步回调,执行时机晚于authenticate方法返回的时机,自然无法向外层方法返回结果,同步取结果必须用blockingGet。
  • 关于第一种协程写法报错:join是suspend方法,只能在协程作用域内调用,你不需要额外launch再join,直接在runBlocking内部执行挂起函数拿结果即可,也就是第二种写法的逻辑。
  • 关于runBlocking是否会阻塞UI线程:完全不会,OkHttp的authenticate回调本身运行在OkHttp自建的后台线程池,runBlocking阻塞的只是当前这个后台工作线程,和UI线程完全隔离,不会导致应用卡死。

额外注意事项

  • 要添加失败处理逻辑,刷新Token失败时直接返回null,避免OkHttp无限重试。
  • 建议加互斥锁(比如使用Mutex),避免多个请求同时触发401时,重复调用刷新Token接口导致refresh token失效。

内容的提问来源于stack exchange,提问作者Shahryar Khosravi

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.16 06:45:03