Hilt提供需异步初始化接口实例:Firebase令牌请求头拦截实现方案
解决方案
你遇到的核心问题是回调式API无法在同步执行的OkHttp拦截器中返回处理结果,我们可以通过Tasks.await()方法将Firebase的异步Task转为同步调用,直接拿到Token结果。由于OkHttp拦截器本身运行在独立的后台线程,阻塞操作不会影响主线程运行,也不会干扰上层Retrofit suspend方法的协程调用逻辑。
改造后的完整实现代码
1. 修正后的Hilt模块代码
我们直接将OkHttpClient的创建逻辑放到Hilt模块中管理,避免使用全局变量,符合依赖注入规范:
@Module @InstallIn(SingletonComponent::class) object CountriesModule { private const val CLOUD_RUN_BASE_URL = "https://my-base-url/" @Provides fun provideOkHttpClient(): OkHttpClient { return OkHttpClient.Builder() .addInterceptor { chain -> val requestBuilder = chain.request().newBuilder() val currentUser = FirebaseAuth.getInstance().currentUser currentUser?.let { user -> try { // 异步Task转同步调用,阻塞直到获取到Token结果 val idTokenResult = Tasks.await(user.getIdToken(true)) val token = idTokenResult.token requestBuilder.addHeader("Authorization", "Bearer $token") } catch (e: Exception) { // 捕获Token获取异常,可根据业务需求调整处理逻辑 Log.d("id_token", "Token获取失败: ${e.message}") } } // 统一返回最终处理后的请求 return@addInterceptor chain.proceed(requestBuilder.build()) } .build() } @Provides fun provideCountriesService(okHttpClient: OkHttpClient): CountriesService { return Retrofit.Builder() .client(okHttpClient) .baseUrl(CLOUD_RUN_BASE_URL) .addConverterFactory(GsonConverterFactory.create()) .build() .create(CountriesService::class.java) } }
注意事项
- 如果不需要每次请求都强制刷新Token,可以把
getIdToken(true)的入参改为false,Firebase会自动返回缓存的有效Token,过期时自动刷新,性能更优 - 如果业务要求未登录用户不能访问接口,可以在用户为空或者Token获取失败的场景下直接抛出自定义异常,上层调用时统一捕获处理即可
- 不需要额外添加依赖,只要集成了Firebase Auth默认就包含
Tasks.await()方法
内容的提问来源于stack exchange,提问作者Urchboy
相关产品推荐
相关产品推荐

