英文:
Flutter FireStore: Unable to reverse a firebase snapshot list
问题
I am developing a chat app using firebase and flutter. When i type a msg the order of the message appearing is random. I want the messages to appear by timestamp. I am really new to coding. Can someone help me out?
For ex:
I just typed-this
And the messaged just appeared at some random place-Should have appeared after last message
Here's the code:-
class MessagesStream extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return StreamBuilder<QuerySnapshot>(
      builder: (context, snapshot) {
        if (!snapshot.hasData) {
          return Center(
            child: CircularProgressIndicator(
              backgroundColor: Colors.lightBlueAccent,
            ),
          );
        }
        final messages = snapshot.data!.docs.reversed;
        List<MessageBubble> messageBubbles = [];
        for (var message in messages) {
          final messageText = message['text'];
          final messageSender = message['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(horizontal: 10.0, vertical: 20.0),
            children: messageBubbles,
          ),
        );
      },
      stream: _firestore.collection('messages').snapshots(),
    );
  }
}
class MessageBubble extends StatelessWidget {
  const MessageBubble({
    super.key,
    required this.sender,
    required this.text,
    required this.isMe,
  });
  final String sender;
  final String text;
  final bool isMe;
  @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: 12,
              color: Colors.black54,
            ),
          ),
          Material(
            elevation: 5,
            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),
                  ),
            color: isMe ? Colors.lightBlueAccent : Colors.white,
            child: Padding(
              padding: EdgeInsets.symmetric(vertical: 10, horizontal: 20),
              child: Text(
                text,
                style: TextStyle(
                  color: isMe ? Colors.white : Colors.black,
                  fontSize: 15,
                ),
              ),
            ),
          ),
        ],
      ),
    );
  }
}
I tried .reverese but didn't work!
final messages = snapshot.data!.docs.reversed;
But it didn't work. I am really new to this, Please help me on this stackoverflow gods.
英文:
I am developing a chat app using firebase and flutter. When i type a msg the order of the message appearing is random. I want the messages to appear by timestamp. I am really new to coding. Can someone help me out?
For ex:
I just typed-this
And the messaged just appeared at some random place-Should have appeared after last message
Here's the code:-
class MessagesStream extends StatelessWidget {
@override
Widget build(BuildContext context) {
return StreamBuilder<QuerySnapshot>(
builder: (context, snapshot) {
if (!snapshot.hasData) {
return Center(
child: CircularProgressIndicator(
backgroundColor: Colors.lightBlueAccent,
),
);
}
final messages = snapshot.data!.docs.reversed;
List<MessageBubble> messageBubbles = [];
for (var message in messages) {
final messageText = message['text'];
final messageSender = message['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(horizontal: 10.0, vertical: 20.0),
children: messageBubbles,
),
);
},
stream: _firestore.collection('messages').snapshots(),
);
}
}
class MessageBubble extends StatelessWidget {
const MessageBubble({
super.key,
required this.sender,
required this.text,
required this.isMe,
});
final String sender;
final String text;
final bool isMe;
@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: 12,
color: Colors.black54,
),
),
Material(
elevation: 5,
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),
),
color: isMe ? Colors.lightBlueAccent : Colors.white,
child: Padding(
padding: EdgeInsets.symmetric(vertical: 10, horizontal: 20),
child: Text(
text,
style: TextStyle(
color: isMe ? Colors.white : Colors.black,
fontSize: 15,
),
),
),
),
],
),
);
}
}
I tried .reverese but didn't work!
final messages = snapshot.data!.docs.reversed;
But it didn't work. I am really new to this, Please help me on this stackoverflow gods.
答案1
得分: 1
你需要为你的消息添加一个时间戳字段,然后在查询中使用.orderBy()方法来获取最新的消息。
时间戳字段可以是DateTime类型或int类型。
DateTime
这种方法稍微复杂一些,但可以直接在代码中使用DateTime类型。
- 创建一个DateTime转换器
 
class DateTimestampConverter implements JsonConverter<DateTime?, Timestamp?> {
  const DateTimestampConverter();
  @override
  DateTime? fromJson(Timestamp? timestamp) => timestamp?.toDate();
  @override
  Timestamp? toJson(DateTime? dateTime) => dateTime != null ? Timestamp.fromDate(dateTime) : null;
}
- 
安装 json_serializable 包。
 - 
在你的消息类上使用 @JsonSerializable 注解
 
part 'message.g.dart';
@JsonSerializable(
  explicitToJson: true,
  converters: [DateTimestampConverter()],
)
class Message {
  String id;
  ...
  factory Message.fromJson(Map<String, dynamic> json) => _$MessageFromJson(json);
  Map<String, dynamic> toJson() => _$MessageToJson(this);
}
- 运行构建命令
 
flutter packages pub run build_runner build --delete-conflicting-outputs
Int
另外一种方法是将timeCreated字段保存为一个int,如下所示:
Message newMessage = Message(
  timeCreated: DateTime.now().millisecondsSinceEpoch,
)
英文:
You need to add a timestamp field to your messages and then use the .orderBy() method in your query to get the latest messages.
https://firebase.google.com/docs/firestore/query-data/order-limit-data
The timestamp field can either be a DateTime or an int.
DateTime
This way is a little more involved but it let's you directly use the DateTime type in your code.
- Create a DateTimeConverter
 
class DateTimestampConverter implements JsonConverter<DateTime?, Timestamp?> {
const DateTimestampConverter();
@override
DateTime? fromJson(Timestamp? timestamp) => timestamp?.toDate();
@override
Timestamp? toJson(DateTime? dateTime) => dateTime != null ? Timestamp.fromDate(dateTime) : null;
}
- 
Install the json_serializable package.
 - 
Annotate your message class with the @JsonSerializable annotation
 
part 'message.g.dart';
@JsonSerializable(
explicitToJson: true,
converters: [DateTimestampConverter()],
)
class Message {
String id;
...
factory Message.fromJson(Map<String, dynamic> json) => _$MessageFromJson(json);
Map<String, dynamic> toJson() => _$MessageToJson(this);
}
- Run the build runner
 
flutter packages pub run build_runner build --delete-conflicting-outputs
Int
Alternatively, save the timeCreated field as an int like this:
Message newMessage = Message(
timeCreated: DateTime.now().millisecondsSinceEpoch,
)
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。


评论