Приложение для чата показывает сообщения случайным образом, когда пользователь отправляет сообщение, а сообщения находятся в неправильном порядке

# #android #firebase #flutter #dart #google-cloud-firestore

Вопрос:

Я создал базовое приложение для чата с помощью 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),),
              )
          ),
        ],
      ),
    );
  }
}
 

Комментарии:

1. Насколько я могу судить, ваш код нигде не указывает порядок для данных — так что это, вероятно, объясняет, почему сообщения отображаются в неопределенном порядке.

2. Хорошо, спасибо за ответ, я постараюсь уточнить какой-нибудь заказ.

3. Спасибо, что это сработало. и извините за позднюю благодарность.

Ответ №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) {