Kotlin/Firebase:从Firebase数据库获取数据时出现「Client is offline」错误
我完全懂你的困扰——UID传对了、路径也没错,其他Firebase功能都正常跑,偏偏拿单个用户信息时就弹出「Client is offline」错误,而且addValueEventListener虽然有人推荐,但它会持续监听数据变化,不符合你只展示一次单用户数据的需求对吧?
给你几个针对性的解决方案,按优先级尝试:
1. 用addListenerForSingleValueEvent替代get(),配合强制同步
get()是Firebase后来推出的简化API,但某些场景下会优先读取本地缓存(哪怕网络正常),导致误报离线。addListenerForSingleValueEvent是更成熟的单次获取数据的方式,再加上keepSynced(true)强制节点和云端同步,能有效解决这个问题:
private fun getData(userCheck: String) { database = FirebaseDatabase.getInstance().getReference("Users").child(userCheck) // 强制该节点与云端同步,避免优先读取本地缓存 database!!.keepSynced(true) database!!.addListenerForSingleValueEvent(object : ValueEventListener { override fun onDataChange(snapshot: DataSnapshot) { if(snapshot.exists()){ val firstName = snapshot.child("firstName").value val lastName = snapshot.child("lastName").value val position = snapshot.child("position").value val email = snapshot.child("email").value tv_Imie.text = firstName.toString() tv_Nazwisko.text = lastName.toString() tv_Stanowisko.text = position.toString() tv_Email.text = email.toString() }else{ Toast.makeText(this@Profil, "User does not exist", Toast.LENGTH_SHORT).show() } } override fun onCancelled(error: DatabaseError) { Toast.makeText(this@Profil, "Failed: ${error.message}", Toast.LENGTH_SHORT).show() Log.e("firebase", "Error getting data", error.toException()) } }) }
这个方法只会触发一次数据读取,完美匹配你展示单用户信息的需求,同时解决了缓存导致的离线错误。
2. 检查离线持久化设置
如果你之前开启了全局离线持久化,可能会出现缓存与云端不同步的情况。可以尝试在Application类或者Activity的onCreate中临时关闭(如果你的应用不依赖离线功能):
FirebaseDatabase.getInstance().setPersistenceEnabled(false)
如果需要保留离线功能,就不用全局关闭,方案1里的keepSynced(true)已经能针对单个节点强制同步了。
3. 升级Firebase SDK版本
「Client is offline」确实是某些旧版本SDK的已知bug,建议你把Firebase Realtime Database的依赖升级到最新稳定版。在Module级别的build.gradle里修改:
implementation 'com.google.firebase:firebase-database:20.3.0' // 替换为当前最新版本
4. 辅助排查:验证设备网络状态
虽然你觉得网络没问题,但可以加个简单的检查,确认设备确实在线,避免误判:
private fun isNetworkAvailable(): Boolean { val connectivityManager = getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager val networkInfo = connectivityManager.activeNetworkInfo return networkInfo != null && networkInfo.isConnected }
在调用getData前先检查,如果网络不在线就给用户提示,排除网络本身的问题。
先试方案1,大部分情况下都能解决问题,如果不行再依次排查后面的方法。
内容的提问来源于stack exchange,提问作者Matthew Kna

