【问题标题】:Chat app showing messages randomly when user sends a message and messages are not in proper order当用户发送消息并且消息顺序不正确时,聊天应用程序随机显示消息
【发布时间】:2021-07-06 16:32:19
【问题描述】:

完成教程后,我使用 firebase 制作了一个基本的聊天应用程序。但该应用程序并不总是按顺序显示消息。另外,我的消息应该从底部开始,但并非总是如此。

我已经实现了这样的 firebase 和 firestore 软件包,因为我在提及版本时收到了错误消息。

dependencies:
  flutter:
    sdk: flutter


  cupertino_icons: ^0.1.2
  animated_text_kit: ^4.1.1
  firebase_core:
  firebase_auth:
  cloud_firestore:
  modal_progress_hud: ^0.1.3

在教程中,显示​​您必须在文档之后添加 .reversed,如下面的代码。

final messages = snapshot.data.documents.reversed;

但是当我尝试做同样的事情时,文档属性不存在,我们必须使用.docs 然后我尝试在文档之后添加.reversed,但问题仍然存在并且消息随机出现。如教程所示,我还尝试从 firebase 中删除该集合。

下面是获取消息流的代码。

class streamOfMessages extends StatelessWidget {
  const streamOfMessages({@required this.users,});
  final CollectionReference users;

  @override
  Widget build(BuildContext context) {
    return StreamBuilder(
        stream: users.snapshots(),
        // ignore: missing_return
        builder: (BuildContext context, AsyncSnapshot<QuerySnapshot> snapshot){
          if(!snapshot.hasData){
            return Center(
              child: CircularProgressIndicator(
                backgroundColor: Colors.blueAccent,
              ),
            );
          }
          final messages = snapshot.data.docs.reversed;
          List<messageBubble> messageWidgets = [];
          for(var message in messages){
            final messageText = message.data()['text'];
            final messageSender = message.data()['sender'];
            final messageWidget = messageBubble(
              message: messageText,
              sender: messageSender,
              isMe: userEmail == messageSender,
            );
            messageWidgets.add(messageWidget);
          }
          return Expanded(
            child: ListView(
              children: messageWidgets,
              reverse: true,
            ),
          );
        });
  }
}

我也尝试添加时间戳,但我认为我做错了什么。任何帮助都非常感谢谢谢。

我在 ChatScreen dart 文件中编写了一个代码,我在其中定义了所有内容,例如显示消息和文本编辑内容。

其他一切正常,只是消息显示顺序错误。

下面是聊天界面的全部代码

非常感谢任何帮助。

import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flash_chat/constants.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:cloud_firestore/cloud_firestore.dart';


final _auth = FirebaseAuth.instance;
final _firestore = FirebaseFirestore.instance;
String userEmail;

class ChatScreen extends StatefulWidget {
  static String id = 'chat_screen';
  @override
  _ChatScreenState createState() => _ChatScreenState();
}

class _ChatScreenState extends State<ChatScreen> {

  final messageController = TextEditingController();
  CollectionReference users = FirebaseFirestore.instance.collection('messages');
  String messageText;

  @override
  void initState() {
    super.initState();
    loggeduser();
  }

  void loggeduser(){
    try{
      final user = _auth.currentUser;
      if(user != null){
       print(user.email);
       userEmail = user.email;
      }
    }catch(e){
      print(e);
    }
  }

  void getMessages() async {
    await for (var snapshot in _firestore.collection('messages').snapshots()){
      for (var message in snapshot.docs){
        print(message.data());
      }
    }
  }
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        leading: null,
        actions: <Widget>[
          IconButton(
              icon: Icon(Icons.logout),
              onPressed: () {
                _auth.signOut();
                Navigator.pop(context);
              }),
        ],
        title: Text('⚡️Chat'),
        centerTitle: true,
        backgroundColor: Colors.lightBlueAccent,
      ),
      body: SafeArea(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.spaceBetween,
          crossAxisAlignment: CrossAxisAlignment.stretch,
          children: <Widget>[
            streamOfMessages(users: users),
            Container(
              decoration: kMessageContainerDecoration,
              child: Row(
                crossAxisAlignment: CrossAxisAlignment.center,
                children: <Widget>[
                  Expanded(
                    child: TextField(
                      controller: messageController,
                      onChanged: (value) {
                        messageText = value;
                      },
                      decoration: kMessageTextFieldDecoration,
                    ),
                  ),
                  FlatButton(
                    onPressed: () {
                      messageController.clear();
                      _firestore.collection('messages').add({
                        'text' : messageText,
                        'sender' : userEmail,
                      });
                    },
                    child: Text(
                      'Send',
                      style: kSendButtonTextStyle,
                    ),
                  ),
                ],
              ),
            ),
          ],
        ),
      ),
    );
  }
}

// ignore: camel_case_types
class streamOfMessages extends StatelessWidget {
  const streamOfMessages({@required this.users,});
  final CollectionReference users;

  @override
  Widget build(BuildContext context) {
    return StreamBuilder(
        stream: users.snapshots(),
        // ignore: missing_return
        builder: (BuildContext context, AsyncSnapshot<QuerySnapshot> snapshot){
          if(!snapshot.hasData){
            return Center(
              child: CircularProgressIndicator(
                backgroundColor: Colors.blueAccent,
              ),
            );
          }
          final messages = snapshot.data.docs.reversed;
          List<messageBubble> messageWidgets = [];
          for(var message in messages){
            final messageText = message.data()['text'];
            final messageSender = message.data()['sender'];
            final messageWidget = messageBubble(
              message: messageText,
              sender: messageSender,
              isMe: userEmail == messageSender,
            );
            messageWidgets.add(messageWidget);
          }
          return Expanded(
            child: ListView(
              children: messageWidgets,
              reverse: true,
            ),
          );
        });
  }
}


// ignore: camel_case_types
class messageBubble extends StatelessWidget {
  final String  message;
  final String sender;
  final bool isMe;
  messageBubble({this.message, this.sender, this.isMe, this.time});
  @override
  Widget build(BuildContext context) {
    return Padding(
      padding: EdgeInsets.all(10.0),
      child: Column(
        crossAxisAlignment: isMe ? CrossAxisAlignment.end : CrossAxisAlignment.start,
        children: [
          Text('$sender',
            style: TextStyle(fontSize:10.0, color: Colors.black54),
          ),
          Material(
            borderRadius: isMe ? BorderRadius.only(topLeft: Radius.circular(30.0),bottomLeft: Radius.circular(30.0),bottomRight: Radius.circular(30.0)) :
            BorderRadius.only(bottomLeft: Radius.circular(30.0),bottomRight: Radius.circular(30.0),topRight: Radius.circular(30.0)),
            elevation: 5.0,
            color: isMe ? Colors.lightBlueAccent : Colors.white,
              child: Padding(
                padding: EdgeInsets.symmetric(vertical: 10.0,horizontal: 10.0),
                child: Text(message,
                style: TextStyle(fontSize: 16.0,
                    color: isMe ? Colors.white : Colors.black54),),
              )
          ),
        ],
      ),
    );
  }
}

【问题讨论】:

  • 据我所知,您的代码没有在任何地方指定 order for the data - 所以这可能可以解释为什么消息以未定义的顺序显示。
  • 好的,谢谢你的回复我会尽量指定一些顺序。
  • 谢谢你成功了。很抱歉迟到了。

标签: android firebase flutter dart google-cloud-firestore


【解决方案1】:

所以我找到了答案,您必须在代码中添加时间戳并将排序方法添加到列表中并解决问题。 以下是完成更改的代码。

"....." = 表示相同的代码无需更改。

               ............
               Expanded(
                    child: TextField(
                      controller: messageController,
                      onChanged: (value) {
                        messageText = value;
                      },
                      decoration: kMessageTextFieldDecoration,
                    ),
                  ),
                  FlatButton(
                    onPressed: () {
                      messageController.clear();
                      _firestore.collection('messages').add({
                        'text' : messageText,
                        'sender' : userEmail,
                        'time' : DateTime.now(),   --------------> Change here
                      });
                      print(DateTime.now());
                    },
                    child: Text(
                      'Send',
                      style: kSendButtonTextStyle,
                    ),..............

下面的另一个变化

.............
     child: CircularProgressIndicator(
                    backgroundColor: Colors.blueAccent,
                  ),
                );
              }
              final messages = snapshot.data.docs.reversed;
              List<messageBubble> messageWidgets = [];
              for(var message in messages){
                final messageText = message.data()['text'];
                final messageSender = message.data()['sender'];
                final messageTime = message.data()['time'];   ---------> added
                final messageWidget = messageBubble(
                  message: messageText,
                  sender: messageSender,
                  isMe: userEmail == messageSender,
                  time: messageTime, -----------------------------------> Add this
                );
                messageWidgets.add(messageWidget);  -----------------------------> Add bot 
                messageWidgets.sort((a , b ) => b.time.compareTo(a.time)); ------> h lines
              }
              return Expanded(
                child: ListView(
                  children: messageWidgets,
                  reverse: true,
                ),
              );

在另一个变化之下

.............
class messageBubble extends StatelessWidget {
  final String  message;
  final String sender;
  final bool isMe;
  final Timestamp time;  ------------------> This is added
  messageBubble({this.message, this.sender, this.isMe, this.time}); ----> add this.time
  @override
  Widget build(BuildContext context) {

【讨论】:

    猜你喜欢
    • 2020-11-30
    • 1970-01-01
    • 1970-01-01
    • 2019-05-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-10-04
    • 1970-01-01
    相关资源
    最近更新 更多