颤振聊天应用程序上的消息顺序不正确

Kit*_*awa 6 flutter

我刚刚根据教程完成了这个基本的聊天应用程序,但我的消息并不总是从底部开始。

当我删除时,保存并重新添加 .reversed 在这一行:

final messages = snapshot.data.documents.reversed;
Run Code Online (Sandbox Code Playgroud)

那么它似乎重新排序正确,但下一条消息又是随机的。

唯一的区别是我使用了更新的 firebase 插件。

  • -firebase_core: 0.4.0+8, 教程是 ^0.3.4
    -firebase_auth: 0.14.0+1, 教程是 ^0.8.4+4
    -cloud_firestore: 0.12.9, 教程是 ^0.9.13+1

//消息流代码

class MessagesStream extends StatelessWidget {

@override
Widget build(BuildContext context) {
return StreamBuilder<QuerySnapshot>(
stream: _firestore.collection('messages').snapshots(),
builder: (context, snapshot) {
if (!snapshot.hasData) {
return Center(
child: CircularProgressIndicator(
 backgroundColor: Colors.lightBlue,
    ),
  );
}
final messages = snapshot.data.documents.reversed;
List<MessageBubble> messageBubbles = [];
for (var message in messages) {
  final messageText = message.data['text'];
  final messageSender = message.data['sender'];

  final currentUser = loggedInUser.email;

  final messageBubble = MessageBubble(
    sender: messageSender,
    text: messageText,
    isMe: currentUser == messageSender,
  );

  messageBubbles.add(messageBubble);
}
return Expanded(
  child: ListView(
    reverse: true,
    padding: EdgeInsets.symmetric(vertical: 20.0, horizontal: 10.0),
    children: messageBubbles,
    ),
   );
  },
);
}
}
Run Code Online (Sandbox Code Playgroud)

除了随机顺序外,一切正常,消息保存在 firebase 中。也许我需要添加时间码或其他东西才能使它工作。

任何帮助表示赞赏 - 谢谢。

GAU*_*SHI 10

应用此代码后,就像安吉拉在她的课程视频中所做的那样,删除 firebase 中的数据库。然后重新启动应用程序。你的应用程序会工作。此外,在代码中,我添加了有关您必须添加的内容的说明。仅添加它们。我遇到了同样的问题,所以我在编码器的帮助下解决了这个问题。所以它也适用于你的代码。

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 _fireStore = Firestore.instance;
FirebaseUser loggedInUser;

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

class _ChatScreenState extends State<ChatScreen> {
  final messageTextEditingController = TextEditingController();
  String messageText;

  final _auth = FirebaseAuth.instance;

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

  void getUserDetail() async {
    try {
      final createdUser = await _auth.currentUser();
      if (createdUser != null) {
        loggedInUser = createdUser;
      }
    } catch (e) {
      print(e);
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        leading: null,
        actions: <Widget>[
          IconButton(
              icon: Icon(Icons.close),
              onPressed: () {

                _auth.signOut();
                Navigator.pop(context);
              }),
        ],
        title: Text('??Chat'),
        backgroundColor: Colors.lightBlueAccent,
      ),
      body: SafeArea(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.spaceBetween,
          crossAxisAlignment: CrossAxisAlignment.stretch,
          children: <Widget>[
            StreambuilderClass(),
            Container(
              decoration: kMessageContainerDecoration,
              child: Row(
                crossAxisAlignment: CrossAxisAlignment.center,
                children: <Widget>[
                  Expanded(
                    child: TextField(
                      controller: messageTextEditingController,
                      onChanged: (value) {
                        messageText = value;
                      },
                      decoration: kMessageTextFieldDecoration,
                    ),
                  ),
                  FlatButton(
                    onPressed: () {
                      messageTextEditingController.clear();
                      _fireStore.collection('messages').add({
                        'sender': loggedInUser.email,
                        'text': messageText,
                        'time': FieldValue.serverTimestamp() //add this
                      });
                    },
                    child: Text(
                      'Send',
                      style: kSendButtonTextStyle,
                    ),
                  ),
                ],
              ),
            ),
          ],
        ),
      ),
    );
  }
}

class StreambuilderClass extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return StreamBuilder<QuerySnapshot>(
        stream: _fireStore
            .collection('messages')
            .orderBy('time', descending: false)//add this
            .snapshots(),
        builder: (context, snapshot) {
          if (!snapshot.hasData) {
            return Center(
              child: CircularProgressIndicator(
                backgroundColor: Colors.blueAccent,
              ),
            );
          }
          final messages = snapshot.data.documents.reversed;
          List<MessageBubble> messageBubbles = [];
          for (var message in messages) {
            final messageText = message.data['text'];
            final messageSender = message.data['sender'];
            final messageTime = message.data['time'] as Timestamp; //add this
            final currentUser = loggedInUser.email;

            final messageBubble = MessageBubble(
              sender: messageSender,
              text: messageText,
              isMe: currentUser == messageSender,
              time: messageTime, //add this
            );

            messageBubbles.add(messageBubble);
          }

          return Expanded(
            child: ListView(
                reverse: true,
                padding: EdgeInsets.symmetric(horizontal: 10, vertical: 20),
                children: messageBubbles),
          );
        });
  }
}

class MessageBubble extends StatelessWidget {
  final String text;
  final String sender;
  final bool isMe;
  final Timestamp time; // add this

  MessageBubble({this.text, this.sender, this.isMe, this.time}); //add the variable  in this constructor
  @override
  Widget build(BuildContext context) {
    return Padding(
      padding: EdgeInsets.all(10.0),
      child: Column(
        crossAxisAlignment:
            isMe ? CrossAxisAlignment.end : CrossAxisAlignment.start,
        children: <Widget>[
          Text(
            ' $sender ${DateTime.fromMillisecondsSinceEpoch(time.seconds * 1000)}',// add this only if you want to show the time along with the email. If you dont want this then don't add this DateTime thing
            style: TextStyle(color: Colors.black54, fontSize: 12),
          ),
          Material(
            color: isMe ? Colors.blueAccent : Colors.white,
            borderRadius: isMe
                ? BorderRadius.only(
                    topLeft: Radius.circular(30),
                    bottomLeft: Radius.circular(30),
                    bottomRight: Radius.circular(30))
                : BorderRadius.only(
                    topRight: Radius.circular(30),
                    bottomLeft: Radius.circular(30),
                    bottomRight: Radius.circular(30)),
            elevation: 6,
            child: Padding(
              padding: EdgeInsets.symmetric(horizontal: 20, vertical: 15),
              child: Text(
                text,
                style: TextStyle(
                    fontSize: 20, color: isMe ? Colors.white : Colors.black),
              ),
            ),
          ),
        ],
      ),
    );
  }
}
Run Code Online (Sandbox Code Playgroud)

  • 嗨,也许你可以用问题的代码更好地解释问题,而不是再次粘贴整个代码。另外,没有人关心安吉拉,无论是谁:-)(我*假设*要点是,firestore 不保证保持创建顺序,并且您必须添加一个可用于排序的属性(时间)?) (2认同)

Kit*_*awa 6

这是完整的工作解决方案。感谢 jquevedo 和 appbrewery。

\n\n
import \'package:flutter/cupertino.dart\';\nimport \'package:flutter/material.dart\';\nimport \'package:flash_chat/constants.dart\';\nimport \'package:firebase_auth/firebase_auth.dart\';\nimport \'package:cloud_firestore/cloud_firestore.dart\';\n\nfinal _firestore = Firestore.instance;\nFirebaseUser loggedInUser;\n\nclass ChatScreen extends StatefulWidget {\n  static const String id = "chat_screen";\n\n  @override\n  _ChatScreenState createState() => _ChatScreenState();\n}\n\nclass _ChatScreenState extends State<ChatScreen> {\n  final messageTextContoller = TextEditingController();\n  final _auth = FirebaseAuth.instance;\n\n  String messageText;\n\n  @override\n  void initState() {\n    super.initState();\n    getCurrentUser();\n  }\n\n  void getCurrentUser() async {\n    try {\n      final user = await _auth.currentUser();\n      if (user != null) {\n        loggedInUser = user;\n        print(loggedInUser.email);\n      }\n    } catch (e) {\n      print(e);\n    }\n  }\n\n  void messagesStream() async {\n    await for (var snapshot in _firestore.collection("messages").snapshots()) {\n      for (var message in snapshot.documents) {\n        print(message.data);\n      }\n    }\n  }\n\n  @override\n  Widget build(BuildContext context) {\n    return Scaffold(\n      appBar: AppBar(\n        leading: null,\n        actions: <Widget>[\n          IconButton(\n              icon: Icon(Icons.close),\n              onPressed: () {\n                _auth.signOut();\n                Navigator.pop(context);\n              }),\n        ],\n        title: Text(\'\xe2\x9a\xa1\xef\xb8\x8fChat\'),\n        backgroundColor: Colors.lightBlueAccent,\n      ),\n      body: SafeArea(\n        child: Column(\n          mainAxisAlignment: MainAxisAlignment.spaceBetween,\n          crossAxisAlignment: CrossAxisAlignment.stretch,\n          children: <Widget>[\n            MessagesStream(),\n            Container(\n              decoration: kMessageContainerDecoration,\n              child: Row(\n                crossAxisAlignment: CrossAxisAlignment.center,\n                children: <Widget>[\n                  Expanded(\n                    child: TextField(\n                      controller: messageTextContoller,\n                      onChanged: (value) {\n                        messageText = value;\n                      },\n                      decoration: kMessageTextFieldDecoration,\n                    ),\n                  ),\n                  FlatButton(\n                    onPressed: () {\n                      messageTextContoller.clear();\n                      _firestore.collection("messages").add({\n                        "text": messageText,\n                        "sender": loggedInUser.email,\n                        "time": DateTime.now()\n                      });\n                    },\n                    child: Text(\n                      \'Send\',\n                      style: kSendButtonTextStyle,\n                    ),\n                  ),\n                ],\n              ),\n            ),\n          ],\n        ),\n      ),\n    );\n  }\n}\n\nclass MessagesStream extends StatelessWidget {\n  @override\n  Widget build(BuildContext context) {\n    return StreamBuilder<QuerySnapshot>(\n      stream: _firestore.collection("messages").snapshots(),\n      // ignore: missing_return\n      builder: (context, snapshot) {\n        if (!snapshot.hasData) {\n          return Center(\n            child: CircularProgressIndicator(\n              backgroundColor: Colors.lightBlueAccent,\n            ),\n          );\n        }\n        final messages = snapshot.data.documents;\n        List<MessageBubble> messageBubbles = [];\n        for (var message in messages) {\n          final messageText = message.data[\'text\'];\n          final messageSender = message.data["sender"];\n          final messageTime = message.data["time"];\n          final currentUsser = loggedInUser.email;\n          final messageBubble = MessageBubble(\n            sender: messageSender,\n            text: messageText,\n            time: messageTime,\n            isMe:  currentUsser == messageSender,\n          );\n          messageBubbles.add(messageBubble);\n          messageBubbles.sort((a , b ) => b.time.compareTo(a.time));\n        }\n        return Expanded(\n          child: ListView(\n            reverse: true,\n            padding: EdgeInsets.symmetric(horizontal: 10.0, vertical: 20),\n            children: messageBubbles,\n          ),\n        );\n      },\n    );\n  }\n}\n\nclass MessageBubble extends StatelessWidget {\n  final String sender;\n  final String text;\n  final Timestamp time;\n  final bool isMe;\n\n  MessageBubble({this.sender, this.text, this.isMe, this.time});\n\n  @override\n  Widget build(BuildContext context) {\n    return Padding(\n      padding: EdgeInsets.all(10.0),\n      child: Column(\n        crossAxisAlignment: isMe ? CrossAxisAlignment.end : CrossAxisAlignment.start,\n        children: <Widget>[\n          Text(\n            "$sender ${time.toDate()}",\n            style: TextStyle(\n              color: Colors.grey,\n              fontSize: 12,\n            ),\n          ),\n          Material(\n            borderRadius: isMe ? BorderRadius.only(\n              topLeft: Radius.circular(30),\n              bottomLeft: Radius.circular(30),\n              bottomRight: Radius.circular(30),\n            ) : BorderRadius.only(\n              topRight: Radius.circular(30),\n              bottomLeft: Radius.circular(30),\n              bottomRight: Radius.circular(30),\n            ),\n            elevation: 5.0,\n            color: isMe ? Colors.lightBlueAccent : Colors.purpleAccent,\n            child: Padding(\n              padding: EdgeInsets.symmetric(\n                vertical: 10,\n                horizontal: 20,\n              ),\n              child: Text(\n                text,\n                style: TextStyle(\n                  fontSize: 15,\n                  color: Colors.white,\n                ),\n              ),\n            ),\n          ),\n        ],\n      ),\n    );\n  }\n}\n\n
Run Code Online (Sandbox Code Playgroud)\n


归档时间:

查看次数:

4667 次

最近记录:

4 年,5 月 前