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

Android设备联网后Firestore仍返回客户端离线异常求助

Firestore 恢复联网后仍返回"Client is Offline"异常的问题解析

我遇到过不少开发者反馈这个棘手的问题,结合你提供的细节和官方的反馈,咱们来拆解下问题根源和可行的临时解决方案:

问题复盘

你已经做了正确的配置:禁用了Firestore的本地持久化(setPersistenceEnabled(false)),确认设备恢复联网后其他网络请求正常,但Firestore的文档获取请求却不稳定地抛出Failed to get document because the client is offline异常——有时马上成功,有时重试多次甚至等一分钟才恢复。升级SDK版本到11.8.0、甚至firestore-core 17.0.4也没能解决。

核心原因

根据你提到的官方确认,这是Firestore Android SDK内部的网络状态同步延迟问题:当设备从离线(比如飞行模式)恢复联网时,系统层面的网络状态已经更新,但Firestore客户端内部的连接检测机制没有及时同步这个状态,导致SDK仍然认为自己处于离线状态,从而拒绝发起网络请求。即使禁用了持久化,这个内部状态不同步的问题依然存在。

临时缓解方案

虽然官方还没给出修复时间表,但可以试试这几个方案来降低问题影响:

1. 主动触发网络重连

在确认设备联网后,主动调用enableNetwork()方法(即使已经禁用持久化,这个方法也能触发SDK重新检测网络连接状态),等重连成功后再发起请求:

// 先通过ConnectivityManager确认网络可用后执行
firestore.enableNetwork().addOnSuccessListener {
    // 网络连接已被Firestore确认,发起文档请求
    val docRef = firestore.collection("foo").document("bar")
    docRef.get().addOnCompleteListener { task ->
        if (task.isSuccessful) {
            Log.d("FirestoreSourceSet", "Get document success")
        } else {
            Log.e("FirestoreSourceSet", "Get document error", task.exception)
        }
    }
}

2. 给请求加智能重试机制

因为异常是间歇性的,给Firestore请求加上指数退避重试逻辑,针对"离线"异常自动重试,直到成功或达到最大次数:

private fun fetchDocumentWithRetry(
    docRef: DocumentReference,
    currentRetry: Int = 0,
    maxRetries: Int = 5
) {
    docRef.get().addOnCompleteListener { task ->
        when {
            task.isSuccessful -> {
                Log.d("FirestoreSourceSet", "Get document success")
            }
            currentRetry < maxRetries -> {
                val exception = task.exception
                if (exception is FirebaseFirestoreException && exception.code == FirebaseFirestoreException.Code.UNAVAILABLE) {
                    // 指数退避:每次重试延迟时间翻倍,避免频繁请求
                    val delayMs = (Math.pow(2.0, currentRetry.toDouble()) * 100).toLong()
                    Handler(Looper.getMainLooper()).postDelayed({
                        fetchDocumentWithRetry(docRef, currentRetry + 1, maxRetries)
                    }, delayMs)
                } else {
                    Log.e("FirestoreSourceSet", "Non-retryable error", exception)
                }
            }
            else -> {
                Log.e("FirestoreSourceSet", "Max retries reached, request failed", task.exception)
            }
        }
    }
}

// 使用示例
val docRef = firestore.collection("foo").document("bar")
fetchDocumentWithRetry(docRef)

3. 监听Firestore的同步状态

利用addSnapshotsInSyncListener来监听Firestore的内部同步状态,只有当SDK确认同步完成(即网络连接正常)后再发起请求:

val syncListener = firestore.addSnapshotsInSyncListener { isSyncing ->
    // isSyncing为false时,说明Firestore已完成与服务器的同步,连接状态正常
    if (!isSyncing) {
        val docRef = firestore.collection("foo").document("bar")
        docRef.get().addOnCompleteListener { task ->
            // 处理请求结果
        }
        // 移除监听,避免重复触发
        syncListener.remove()
    }
}

官方进展说明

目前官方已经确认这是一个SDK内部的bug,但暂时没有给出具体的修复时间。建议你持续关注Firestore SDK的版本更新日志,一旦官方发布修复版本,及时升级即可。

内容的提问来源于stack exchange,提问作者Matthieu Esnault

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 07:53:29