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

Retrofit:如何确保发起网络请求前等待Firebase Token获取完成?

解决方案

1. 封装Firebase Token的异步获取逻辑

先把Firebase Token的回调转换成可等待的异步操作,避免回调嵌套:

Kotlin 协程实现

class FirebaseTokenManager {
    suspend fun getValidToken(): String {
        return suspendCancellableCoroutine { continuation ->
            FirebaseMessaging.getInstance().token.addOnCompleteListener { task ->
                if (task.isSuccessful) {
                    task.result?.let { token ->
                        continuation.resume(token)
                    } ?: continuation.resumeWithException(IllegalStateException("Token为空"))
                } else {
                    continuation.resumeWithException(task.exception ?: IllegalStateException("获取Token失败"))
                }
            }
        }
    }
}

Java CompletableFuture实现

public class FirebaseTokenManager {
    public CompletableFuture<String> getValidToken() {
        CompletableFuture<String> future = new CompletableFuture<>();
        FirebaseMessaging.getInstance().getToken()
                .addOnCompleteListener(task -> {
                    if (task.isSuccessful()) {
                        String token = task.getResult();
                        if (token != null) {
                            future.complete(token);
                        } else {
                            future.completeExceptionally(new IllegalStateException("Token为空"));
                        }
                    } else {
                        future.completeExceptionally(task.getException() != null ? task.getException() : new IllegalStateException("获取Token失败"));
                    }
                });
        return future;
    }
}

2. 确保网络请求在Token获取完成后执行

Kotlin 协程场景

在Repository或ViewModel中先获取Token,再发起请求:

class ApiRepository(private val tokenManager: FirebaseTokenManager, private val apiService: ApiService) {
    suspend fun fetchData(): Result<DataModel> {
        return try {
            val token = tokenManager.getValidToken()
            val response = apiService.fetchData()
            if (response.isSuccessful) {
                Result.success(response.body()!!)
            } else {
                Result.failure(IOException("请求失败: ${response.code()}"))
            }
        } catch (e: Exception) {
            Result.failure(e)
        }
    }
}

Java CompletableFuture场景

public class ApiRepository {
    private final FirebaseTokenManager tokenManager;
    private final ApiService apiService;

    public ApiRepository(FirebaseTokenManager tokenManager, ApiService apiService) {
        this.tokenManager = tokenManager;
        this.apiService = apiService;
    }

    public CompletableFuture<DataModel> fetchData() {
        return tokenManager.getValidToken()
                .thenCompose(token -> apiService.fetchData())
                .thenApply(response -> {
                    if (response.isSuccessful()) {
                        return response.body();
                    } else {
                        throw new IOException("请求失败: " + response.code());
                    }
                });
    }
}

3. 用Retrofit拦截器自动添加Token到请求头

通过拦截器统一处理请求头,无需每次手动传入Token:

Kotlin 实现

class AuthInterceptor(private val tokenManager: FirebaseTokenManager) : Interceptor {
    override suspend fun intercept(chain: Interceptor.Chain): Response {
        val token = tokenManager.getValidToken()
        val request = chain.request()
                .newBuilder()
                .addHeader("Authorization", "Bearer $token")
                .build()
        return chain.proceed(request)
    }
}

// 构建Retrofit实例
val retrofit = Retrofit.Builder()
        .baseUrl(BASE_URL)
        .addConverterFactory(GsonConverterFactory.create())
        .addCallAdapterFactory(CoroutineCallAdapterFactory())
        .client(OkHttpClient.Builder()
                .addInterceptor(AuthInterceptor(tokenManager))
                .build())
        .build()

Java 实现

public class AuthInterceptor implements Interceptor {
    private final FirebaseTokenManager tokenManager;

    public AuthInterceptor(FirebaseTokenManager tokenManager) {
        this.tokenManager = tokenManager;
    }

    @Override
    public Response intercept(Chain chain) throws IOException {
        String token = tokenManager.getValidToken().join();
        Request request = chain.request()
                .newBuilder()
                .addHeader("Authorization", "Bearer " + token)
                .build();
        return chain.proceed(request);
    }
}

// 构建Retrofit实例
Retrofit retrofit = new Retrofit.Builder()
        .baseUrl(BASE_URL)
        .addConverterFactory(GsonConverterFactory.create())
        .addCallAdapterFactory(CompletableFutureCallAdapterFactory.create())
        .client(new OkHttpClient.Builder()
                .addInterceptor(new AuthInterceptor(tokenManager))
                .build())
        .build();

4. 处理Token过期重试逻辑

如果请求返回401(Token过期),可在拦截器中重新获取Token并重试:

override suspend fun intercept(chain: Interceptor.Chain): Response {
    val token = tokenManager.getValidToken()
    val request = chain.request().newBuilder()
            .addHeader("Authorization", "Bearer $token")
            .build()
    val response = chain.proceed(request)

    if (response.code() == 401) {
        val newToken = tokenManager.getValidToken()
        val newRequest = request.newBuilder()
                .header("Authorization", "Bearer $newToken")
                .build()
        return chain.proceed(newRequest)
    }
    return response
}

内容的提问来源于stack exchange,提问作者Oscar Berggren

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 20:20:21