Flutter和Firebae与单人聊天的简单实现(Firebase Realtime Database)

项目的实现效果

项目的实现效果如上图所示。简单介绍一下项目:假设用户A和用户B是朋友关系,用户A登陆之后朋友列表中有用户B,用户B登陆之后朋友列表中有用户A。点击朋友列表中的一个朋友,可以打开和朋友之间的聊天界面。用户A向用户B发送消息之后,用户B查看消息之后,用户A的聊天界面会显示为已读。

用户之间的聊天记录

上图是用户之间的聊天数据示例。Realtime Database内部是json数据结构,json数据结构是分层的。chats代表所有单人之间的聊天结合。图中的1代表id,两个用户之间的聊天的索引或者key,我们把用户的id和"_"连接形成聊天记录的id。示例代码,如下:

dart 复制代码
String generateChatId(String uid1, String uid2) {
  final uids = [uid1, uid2]..sort();
  return '${uids[0]}_${uids[1]}';
}

注意两个用户的uid需要排序,因为两个用户uid通过"_"连接组合可能有两种可能,如果用sort排序就能保证唯一性。 图中的2代表一条聊天信息的id。图中的3代表消息接受方的id,也就是朋友的id,属性值true代表朋友已经读过这条消息。其中还包括发送方用户的id:senderId,聊天的内容:text,发送消息的时间戳timestamp。

用户之间发送消息

dart 复制代码
Future<void> sendMessage(String myUid, String otherUid, String text) async {
  final chatId = generateChatId(myUid, otherUid);
  final ref = FirebaseDatabase.instance.ref('chats/$chatId/messages').push();

  await ref.set({
    'senderId': myUid,
    'text': text,
    'timestamp': ServerValue.timestamp,
    'readBy': {otherUid: false},
  });
}

示例代码如上所示,也就是向聊天集合中的messages添加一条聊天记录,key是自动生成的唯一的字符串。Realtime Database是低延迟,自动同步的数据库,只要本地数据库数据变动就会收到变化通知,如果网络连接正常,数据会同步到Realtime Database server,同时通知监听数据变化的client端,这在软件设计领域有点像订阅者通知模式,只不过是数据库的订阅通知。用户A向用户B发送消息,用户B收到消息的延迟大概是秒级单位。

标记消息已读

dart 复制代码
 String chatId =  generateChatId(
                  context.read<UserUid>().friend!.uid,
                  _auth.currentUser!.uid,
                );
                DatabaseReference ref = FirebaseDatabase.instance.ref('chats/$chatId/messages/${message.key}/readBy');
                final readBy = message.value['readBy'] as Map<dynamic, dynamic>?;

                if (readBy != null && readBy[_auth.currentUser!.uid] == false) {
                  await ref.update({
                    _auth.currentUser!.uid: true,
                  });
                }

只有readBy中属性名称和当前用户的id一样,并且它的值为false,才会在这条消息显示在屏幕的时候(用户查看)标记为已读。

消息的排序

ini 复制代码
 final messages = data.entries.toList()
          ..sort((a, b) {
            final tsA = a.value['timestamp'] ?? 0;
            final tsB = b.value['timestamp'] ?? 0;
            return tsA.compareTo(tsB);
          });

消息按照时间先后顺序排序,代码逻辑如上所示。

参考资料

项目已经上传到github上,地址是github.com/caiweihao/f... firebase.google.com/docs/databa...

相关推荐
农夫三拳_有点甜3 小时前
Flutter Expanded 组件总结
flutter
火柴就是我4 小时前
跟着官方demo 学flame 之 word 坐标系以及Camera的一些属性
flutter
新镜4 小时前
【Flutter】drag_select_grid_view: ^0.6.2 使用
flutter
程序员老刘5 小时前
Google突然“变脸“,2026年要给全球开发者上“紧箍咒“?
android·flutter·客户端
鹏多多.9 小时前
flutter-使用fluttertoast制作丰富的高颜值toast
android·前端·flutter·ios
新镜1 天前
【Flutter】RefreshIndicator 无法下拉刷新问题
flutter
星秋Eliot1 天前
Flutter的三棵树
前端·flutter
humiaor1 天前
Flutter之riverpod状态管理Widget UI详解
flutter·consumer·widget·hooks·provider·riverpod·hookwidget
农夫三拳_有点甜1 天前
Flutter Stack 组件总结
flutter
MaoJiu1 天前
Flutter混合开发:在iOS工程中嵌入Flutter Module
flutter·ios