Flutter中Firebase Realtime Database .info/connected监听始终返回false
问题描述
在Flutter/Firebase应用中实现用户在线状态追踪(支持按“在线”筛选用户目录),获取用户uid后编写了对应代码,但Firestore的isOnline字段始终被设为false,打印结果显示Realtime Database的.info/connected节点返回值一直为false。
已知信息:
- 安全规则无问题,字段可正常写入;
- 使用安卓模拟器测试;
- 应用未使用Realtime Database的其他功能。
疑问:监听.info/connected返回准确连接状态是否有前置条件?是否因未使用Realtime Database其他功能导致节点未初始化?
相关代码:
void _setUpPresenceListener(String uid) async { // *** Un-used Realtime Database reference to keep the connection alive DatabaseReference userStatusRef = FirebaseDatabase.instance.ref('status/$uid'); // Reference to the .info/connected node in Realtime Database DatabaseReference connectedRef = FirebaseDatabase.instance.ref(".info/connected"); // Firestore reference to the users_presence collection DocumentReference presenceRef = FirebaseFirestore.instance.collection('users_presence').doc(uid); // Listen for connection state changes connectedRef.onValue.listen((event) async { final bool isConnected = event.snapshot.value as bool? ?? false; // *** print("&&& - val: ${event.snapshot.value.toString()}"); // If connected, set isOnline to true in Firestore if (isConnected) { await presenceRef.set({ 'isOnline': true, 'lastChanged': FieldValue.serverTimestamp(), }); } else { // When disconnected, set isOnline to false await presenceRef.set({ 'isOnline': false, 'lastChanged': FieldValue.serverTimestamp(), }); } }); }
问题原因与解决方案
Realtime Database连接未触发
.info/connected节点的状态依赖Realtime Database的活跃连接,仅创建引用不会触发连接建立。你代码中的userStatusRef只是声明了引用但未执行任何读写或监听操作,Firebase不会主动维持该连接,导致.info/connected始终返回false。主动触发Realtime Database连接
需要对Realtime Database的真实节点执行至少一次读写或监听操作来建立连接。比如给userStatusRef添加一个空监听:// 添加此行触发Realtime Database连接 userStatusRef.onValue.listen((_) {});或者初始化时写入一个占位值:
await userStatusRef.set({'dummy': true});修复离线状态的写入逻辑
当前代码在设备离线时无法执行else分支的Firestore写入(离线时客户端无法主动触发),需结合Realtime Database的onDisconnect机制,在连接建立时预设断开后的操作,配合云函数实现可靠的离线状态更新:if (isConnected) { await presenceRef.set({ 'isOnline': true, 'lastChanged': FieldValue.serverTimestamp(), }); // 预设断开连接时的标记写入 await userStatusRef.onDisconnect().set({'disconnectedAt': ServerValue.timestamp}); // 配合云函数监听status节点的变化,当检测到disconnectedAt时,更新Firestore的isOnline为false }服务器会在检测到连接断开时自动执行
onDisconnect预设的操作,云函数监听该节点变化后即可更新Firestore的用户在线状态。检查模拟器网络
确认安卓模拟器的网络连接正常,可尝试切换网络模式(如Wi-Fi/蜂窝网络)测试,避免因模拟器网络异常导致无法连接Firebase服务。
内容的提问来源于stack exchange,提问作者Nerdy Bunz

