You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter聊天应用接收方无法查看消息问题求助

问题:Flutter聊天应用接收方无法查看消息

我的Flutter聊天应用出现异常:发送方能看到自身发送的消息,但接收方无法查看消息。我认为Firestore查询语句无误,但无法解决该问题,恳请帮忙排查。若问题源于查询语句,请帮忙修正。

数据库结构说明

使用Firestore存储消息,集合名为messages,每个文档包含以下字段:

  • senderid: 发送方用户UID
  • receiverid: 接收方用户UID
  • Date: 消息发送时间(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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.30 03:25:20