如何使用Flutter实现聊天应用的用户在线/离线状态展示功能
Flutter 聊天应用用户在线/离线状态实现方案
方案1:基于第三方IM服务快速实现
如果你的项目已经接入了第三方IM或实时数据库服务,可以直接用服务自带的状态能力快速落地需求:
- 若使用Firebase Realtime Database/Firestore,可利用官方Presence系统实现:
原理是监听客户端和Firebase的长连接状态,连接建立时标记用户为在线,断开连接时自动触发
onDisconnect预设回调更新为离线状态
核心代码示例:final FirebaseDatabase database = FirebaseDatabase.instance; DatabaseReference userStatusRef = database.ref('users/${currentUser.uid}/status'); // 监听全局连接状态 database.ref('.info/connected').onValue.listen((event) { if (event.snapshot.value as bool == true) { // 连接成功,标记为在线 userStatusRef.set({'state': 'online', 'updateTime': ServerValue.timestamp}); // 配置断开连接时的自动操作 userStatusRef.onDisconnect().set({'state': 'offline', 'lastSeen': ServerValue.timestamp}); } }); - 若使用国内IM服务(融云、腾讯云IM等),SDK一般自带用户状态查询与变更回调能力,直接调用
getUserStatus接口拉取初始状态、监听onUserStatusChanged回调更新UI即可。
方案2:自研后端实现
如果是自研后端架构,需要前后端配合完成三个核心逻辑:
- 客户端状态上报
结合应用生命周期和心跳机制上报状态,避免退后台、断网等场景状态更新不及时
核心代码示例:Timer? heartbeatTimer; // 混入生命周期监听 class _FriendListState extends State<FriendList> with WidgetsBindingObserver { @override void initState() { super.initState(); WidgetsBinding.instance.addObserver(this); startHeartbeat(); updateUserStatus('online'); } // 启动45秒一次的心跳 void startHeartbeat() { heartbeatTimer = Timer.periodic(const Duration(seconds: 45), (timer) async { await http.post(Uri.parse('你的心跳接口地址'), body: {'uid': currentUserId}); }); } // 监听生命周期变更更新状态 @override void didChangeAppLifecycleState(AppLifecycleState state) { super.didChangeAppLifecycleState(state); if (state == AppLifecycleState.resumed) { startHeartbeat(); updateUserStatus('online'); } else if (state == AppLifecycleState.paused) { heartbeatTimer?.cancel(); updateUserStatus('offline'); } } @override void dispose() { WidgetsBinding.instance.removeObserver(this); heartbeatTimer?.cancel(); super.dispose(); } } - 后端状态判定
后端维护所有用户的最后活跃时间戳,超过2个心跳周期未收到上报的用户自动标记为离线,状态变更后主动推送给所有订阅了该用户状态的客户端。 - 客户端状态同步
进入好友列表、聊天页等页面时主动拉取相关用户的最新状态,同时监听后端的状态变更推送,收到变更后立即刷新对应UI节点的状态展示。
UI展示优化建议
- 在线状态优先用绿色小圆点直观标识,离线状态可展示灰色小圆点,或者补充
最后在线于XX分钟前的文案 - 群聊场景默认仅展示在线用户数,点击后再加载全量成员状态,避免大量状态同步带来的性能损耗
内容的提问来源于stack exchange,提问作者Otong Alex
相关产品推荐
相关产品推荐

