Flutter FireStore:无法反转 Firebase 快照列表

huangapple go评论65阅读模式
英文:

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&lt;QuerySnapshot&gt;(
builder: (context, snapshot) {
if (!snapshot.hasData) {
return Center(
child: CircularProgressIndicator(
backgroundColor: Colors.lightBlueAccent,
),
);
}
final messages = snapshot.data!.docs.reversed;
List&lt;MessageBubble&gt; messageBubbles = [];
for (var message in messages) {
final messageText = message[&#39;text&#39;];
final messageSender = message[&#39;sender&#39;];
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(&#39;messages&#39;).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类型。

  1. 创建一个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;
}
  1. 安装 json_serializable 包。

  2. 在你的消息类上使用 @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);

}
  1. 运行构建命令

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.

  1. Create a DateTimeConverter
class DateTimestampConverter implements JsonConverter&lt;DateTime?, Timestamp?&gt; {
const DateTimestampConverter();
@override
DateTime? fromJson(Timestamp? timestamp) =&gt; timestamp?.toDate();
@override
Timestamp? toJson(DateTime? dateTime) =&gt; dateTime != null ? Timestamp.fromDate(dateTime) : null;
}
  1. Install the json_serializable package.

  2. Annotate your message class with the @JsonSerializable annotation

part &#39;message.g.dart&#39;;
@JsonSerializable(
explicitToJson: true,
converters: [DateTimestampConverter()],
)
class Message {
String id;
...
factory Message.fromJson(Map&lt;String, dynamic&gt; json) =&gt; _$MessageFromJson(json);
Map&lt;String, dynamic&gt; toJson() =&gt; _$MessageToJson(this);
}
  1. 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,
)

huangapple
  • 本文由 发表于 2023年2月20日 00:18:59
  • 转载请务必保留本文链接:https://go.coder-hub.com/75501560.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定