Firebase cloud Firestore中的时间字段serverTimestamp()在第一个快照上返回null
我正在从CloudFireStore读取一些数据(消息),在一个文档中,我有一个时间戳字段。 我有一条小溪:Firebase cloud Firestore中的时间字段serverTimestamp()在第一个快照上返回null,firebase,flutter,google-cloud-firestore,timestamp,Firebase,Flutter,Google Cloud Firestore,Timestamp,我正在从CloudFireStore读取一些数据(消息),在一个文档中,我有一个时间戳字段。 我有一条小溪: Stream<QuerySnapshot> get chats { return chatCollection.document(roomid).collection("messages").snapshots(); } 所以没问题。当我从我的代码在我的数据库中添加一个新文档(消息)时,问题就出现了,然后它立即从数据库中得到了更新,我得到了带
Stream<QuerySnapshot> get chats {
return chatCollection.document(roomid).collection("messages").snapshots();
}
所以没问题。当我从我的代码在我的数据库中添加一个新文档(消息)时,问题就出现了,然后它立即从数据库中得到了更新,我得到了带有新消息列表的新快照。但是在大约0.5秒的时间里,我的安卓系统屏幕上出现了一个错误,然后它恢复正常并正确加载了所有消息。该错误是文档特定字段的空指针时间。时间是my Cloud Firestore DB中的时间戳字段
下面是错误:
The following NoSuchMethodError was thrown building:
The method 'toDate' was called on null.
Receiver: null
Tried calling: toDate()
When the exception was thrown, this was the stack:
#0 Object.noSuchMethod (dart:core-patch/object_patch.dart:51:5)
#1 _ChatScreenState._buildMessage (package:flutter_firebase_chat_app/screens/chat/chat_screen.dart:48:43)
#2 _ChatScreenState.build.<anonymous closure>.<anonymous closure> (package:flutter_firebase_chat_app/screens/chat/chat_screen.dart:226:40)
#3 SliverChildBuilderDelegate.build (package:flutter/src/widgets/sliver.dart:448:22)
#4 SliverMultiBoxAdaptorElement._build.<anonymous closure> (package:flutter/src/widgets/sliver.dart:1136:67)
#5 _HashMap.putIfAbsent (dart:collection-patch/collection_patch.dart:140:29)
#6 SliverMultiBoxAdaptorElement._build (package:flutter/src/widgets/sliver.dart:1136:26)
#7 SliverMultiBoxAdaptorElement.performRebuild.processElement (package:flutter/src/widgets/sliver.dart:1082:66)
正如您所看到的,时间字段是唯一接受FieldValue.serverTimestamp()
的字段,因此我认为在将时间戳值分配给字段Time之前,我以某种方式获得了文档的快照。在我得到所有信息后(时间字段不为空)
有什么想法吗?您可以使用Dart中提供的DateTime模块添加数据,而不是使用FieldValue.serverTimestamp() 您可以使用DateTime.now()获取当前日期和时间,然后在从DB获取数据时,您可以根据需要对其进行格式化。我想这会解决你的问题
我也遇到了同样的问题。经过广泛的搜索,我发现这非常有用。 它有助于理解问题和导致问题的流程 使用
DateTime.now()
不是解决方案,因为主要目的是使用FieldValue.serverTimestamp()
是在不同设备之间同步时间,这DateTime.now()
无法解决
现在,关于FieldValue的NULL问题:
我还按照建议使用了sortTime.toDate().toString()
,但时间戳上的值为NULL,因为:
final sortTime = snapshot.data.documents[index].data()["sortTime"];
String serverTime = sortTime == null ? "" : sortTime.toDate().toString();
将此Dart代码作为一个简单的示例进行解释:
发送消息功能:
/// on pressed action (send to firebase, and show message)
/// consider the messageController gets the input from the user
sendMessage(MyUser myUser) async {
if (messageController.text.isNotEmpty){
Map<String, dynamic> chatMessage = {
"senderUid" : myUser.userId,
"text" : messageController.text,
"sortTime" : FieldValue.serverTimestamp(),
};
messageController.text = "";
await addConversationMessages(widget.chatRoomId, chatMessage);
}
}
Future addConversationMessages(String chatRoomId, chatMessage) async {
await chatsCollection
.doc(chatRoomId)
.collection("chats")
.add(chatMessage);
}
小部件列表视图消息(MyUser MyUser){
返回流生成器(
流:聊天信息流,
生成器:(上下文,快照){
如果(!snapshot.hasData){
返回中心(
子对象:循环压缩机指示器(
valueColor:AlwaysStoppedAnimation(颜色(0xFF087E8B)),
)
);
}否则{
返回ListView.builder(
相反:是的,
itemCount:snapshot.data.documents.length,
itemBuilder:(上下文,索引){
final msgText=snapshot.data.documents[index].data()[“text”];
final msgUid=snapshot.data.documents[索引]
.data()[“senderUid”];
final sortTime=snapshot.data.documents[index].data()[“sortTime”];
字符串serverTime=sortTime==null?”:sortTime.toDate().toString();
返回消息(
msgText、serverTime、msgUid);
}
);
}
},
);
}
在堆栈溢出时,不显示代码和文本的图片。将文本复制到问题本身,并将其格式化,以便于阅读、复制和搜索。@DougStevenson我更改了最后一张照片的实际代码。实际上,所有图片都应该被复制的文本替换掉。这当然解决了问题。但是我不明白为什么serverTimestamp有这个问题!在我了解serverTimestamp()之前,我不会回答这篇文章。以下文档可能会回答您的问题:
final sortTime = snapshot.data.documents[index].data()["sortTime"];
String serverTime = sortTime == null ? "" : sortTime.toDate().toString();
/// on pressed action (send to firebase, and show message)
/// consider the messageController gets the input from the user
sendMessage(MyUser myUser) async {
if (messageController.text.isNotEmpty){
Map<String, dynamic> chatMessage = {
"senderUid" : myUser.userId,
"text" : messageController.text,
"sortTime" : FieldValue.serverTimestamp(),
};
messageController.text = "";
await addConversationMessages(widget.chatRoomId, chatMessage);
}
}
Future addConversationMessages(String chatRoomId, chatMessage) async {
await chatsCollection
.doc(chatRoomId)
.collection("chats")
.add(chatMessage);
}
getConversationMessages(String chatRoomId) async {
return await chatsCollection
.doc(chatRoomId)
.collection("chats")
.orderBy("sortTime", descending: true)
.snapshots();
}
Stream chatMessagesStream;
void initState(){
getConversationMessages(widget.chatRoomId)
.then((value){
setState(() {
chatMessagesStream = value;
});
});
super.initState();
}
Widget ListViewMessages(MyUser myUser){
return StreamBuilder(
stream: chatMessagesStream,
builder: (context, snapshot){
if(!snapshot.hasData){
return Center(
child: CircularProgressIndicator(
valueColor: AlwaysStoppedAnimation<Color>(Color(0xFF087E8B)),
)
);
} else {
return ListView.builder(
reverse: true,
itemCount: snapshot.data.documents.length,
itemBuilder: (context, index) {
final msgText = snapshot.data.documents[index].data()["text"];
final msgUid = snapshot.data.documents[index]
.data()["senderUid"];
final sortTime = snapshot.data.documents[index].data()["sortTime"];
String serverTime = sortTime == null ? "" : sortTime.toDate().toString();
return _buildMessage(
msgText, serverTime, msgUid);
}
);
}
},
);
}