Flutter聊天应用接收方无法查看消息问题求助
问题:Flutter聊天应用接收方无法查看消息
我的Flutter聊天应用出现异常:发送方能看到自身发送的消息,但接收方无法查看消息。我认为Firestore查询语句无误,但无法解决该问题,恳请帮忙排查。若问题源于查询语句,请帮忙修正。
数据库结构说明
使用Firestore存储消息,集合名为messages,每个文档包含以下字段:
senderid: 发送方用户UIDreceiverid: 接收方用户UIDDate: 消息发送时间(DateTime类型)message: 消息内容文本
相关代码
消息列表流构建代码
Expanded( child: StreamBuilder( stream:FirebaseFirestore.instance.collection("messages") .where("senderid", isEqualTo: FirebaseAuth.instance.currentUser!.uid) .where("receiverid", isEqualTo: widget.id) .orderBy("Date",descending: false) .snapshots(), builder: (builder,AsyncSnapshot<QuerySnapshot>snapshot){ if(!snapshot.hasData){ return Center(child: CircularProgressIndicator(),); } return ListView.builder( itemCount: snapshot.data!.docs.length, itemBuilder: (itemBuilder, index) { final message = snapshot.data!.docs[index]["message"]; final senderId = snapshot.data!.docs[index]["senderid"]; final currentUser = FirebaseAuth.instance.currentUser; final isMe = senderId == currentUser!.uid; final alignment = isMe ? MainAxisAlignment.end : MainAxisAlignment.start; final messageTextStyle = isMe ? TextStyle(color: Colors.white) : TextStyle(color: Colors.black); final messageColor = isMe ? Colors.blue : Colors.grey.shade300; return Row( mainAxisAlignment: alignment, children: [ Container( margin: EdgeInsets.symmetric(vertical: 10, horizontal: 8), padding: EdgeInsets.symmetric(vertical: 10, horizontal: 16), decoration: BoxDecoration( color: messageColor, borderRadius: BorderRadius.only( topLeft: isMe ? Radius.circular(20) : Radius.circular(0), topRight: isMe ? Radius.circular(0) : Radius.circular(20), bottomLeft: Radius.circular(20), bottomRight: Radius.circular(20), ), ), child: Text( message, style: messageTextStyle, ), ), ], ); }); }), ),
发送消息按钮代码
IconButton( onPressed: ()async { print("ID=="+widget.id); if (messagecontroller.text.isNotEmpty) { FirebaseFirestore.instance.collection("messages").add({ "senderid":FirebaseAuth.instance.currentUser!.uid, "receiverid":widget.id, "Date":DateTime.now(), "message":messagecontroller.text.toString(), }).whenComplete(() { Fluttertoast.showToast(msg: "Send message to ${widget.name}.........", backgroundColor: Colors.grey, timeInSecForIosWeb: 1 ); }); messagecontroller.clear(); } else{ Fluttertoast.showToast(msg: "Please Enter text to send message to ${widget.name}", backgroundColor: Colors.red ); } }, icon: Icon(Icons.send), color: Colors.grey, ),
问题排查与修复方案
核心问题
当前的Firestore查询仅筛选了当前用户作为发送方、widget.id作为接收方的消息,完全忽略了当前用户作为接收方、widget.id作为发送方的消息,这就是接收方看不到消息的根本原因。
修正后的查询语句
方案1:使用whereIn获取双方所有消息
stream: FirebaseFirestore.instance.collection("messages") .where("senderid", whereIn: [FirebaseAuth.instance.currentUser!.uid, widget.id]) .where("receiverid", whereIn: [FirebaseAuth.instance.currentUser!.uid, widget.id]) .orderBy("Date", descending: false) .snapshots(),
方案2:使用Filter.or实现逻辑OR判断
stream: FirebaseFirestore.instance.collection("messages") .where(Filter.or( Filter.and( Filter("senderid", isEqualTo: FirebaseAuth.instance.currentUser!.uid), Filter("receiverid", isEqualTo: widget.id) ), Filter.and( Filter("senderid", isEqualTo: widget.id), Filter("receiverid", isEqualTo: FirebaseAuth.instance.currentUser!.uid) ) )) .orderBy("Date", descending: false) .snapshots(),
注意事项
- 使用
whereIn时,Firestore会要求创建复合索引,首次运行代码会触发报错,控制台会提供创建索引的直接链接,点击即可完成配置。 - 确保Firestore安全规则允许用户读取相关消息,建议配置如下规则:
rules_version = '2'; service cloud.firestore { match /databases/{database}/documents { match /messages/{message} { allow read: if request.auth != null && (resource.data.senderid == request.auth.uid || resource.data.receiverid == request.auth.uid); allow write: if request.auth != null && resource.data.senderid == request.auth.uid; } } }
内容的提问来源于stack exchange,提问作者Muhammad Zohaib
相关产品推荐
相关产品推荐

