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...

相关推荐
亿刀10 小时前
为什么要学习Flutter编译过程
android·flutter
节省钱16 小时前
【Flutter】深入理解 Provider:不仅仅是Consumer
开发语言·前端·flutter·前端框架
江上清风山间明月16 小时前
Flutter 应用如何设计通知服务
android·flutter·通知·通知服务
Carson带你学Android20 小时前
都2025了,【跨平台框架】到底该怎么选?
android·flutter·react native
怀君1 天前
Flutter——Android原生View是如何通过Flutter进行加载
android·flutter
0wioiw01 天前
Flutter基础(前端教程①⑤-API请求转化为模型列成列表展示实战)
flutter
LinXunFeng1 天前
Flutter - 聊天面板库动画生硬?这次让你丝滑个够
前端·flutter·github
0wioiw02 天前
Flutter基础(前端教程①③-单例)
前端·flutter
iFlyCai2 天前
Flutter状态管理篇之ChangeNotifier基础篇(一)
开发语言·flutter·dart