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

相关推荐
Lionel6896 小时前
Flutter 鸿蒙:获取真实轮播图API数据
flutter
千逐687 小时前
《基于 Flutter for OpenHarmony 的沉浸式天气可视化系统设计与实现》
flutter
一只大侠的侠7 小时前
Flutter开源鸿蒙跨平台训练营 Day8获取轮播图网络数据并实现展示
flutter·开源·harmonyos
sugar_hang7 小时前
Flutter 中的 TCP
flutter
子春一9 小时前
Flutter for OpenHarmony:形状拼图:基于路径几何与空间吸附的交互式拼图系统架构解析
flutter·系统架构
ujainu18 小时前
Flutter + OpenHarmony 游戏开发进阶:用户输入响应——GestureDetector 实现点击发射
flutter·游戏·openharmony
hudawei99618 小时前
TweenAnimationBuilder和AnimatedBuilder两种动画的比较
flutter·ui·动画·tweenanimation·animatedbuilder
ujainu18 小时前
Flutter + OpenHarmony 实现无限跑酷游戏开发实战—— 对象池化、性能优化与流畅控制
flutter·游戏·性能优化·openharmony·endless runner
ZH154558913119 小时前
Flutter for OpenHarmony Python学习助手实战:自动化脚本开发的实现
python·学习·flutter
晚烛21 小时前
CANN + 物理信息神经网络(PINNs):求解偏微分方程的新范式
javascript·人工智能·flutter·html·零售