[英]StreamBuilder has data when it shouldn't
我正在使用 Firebase 实时数据库向我的应用程序添加聊天功能。 在数据库中,我有以下数据:
{
events: {
"event-uuid1": {
"chat-uuid1": {
"message": "hey"
},
"chat-uuid2": {
"message": "hey again"
}
}
}
}
在我的 Flutter 应用程序中,我有这个 StreamBuilder(我知道这很长,我不确定问题出在哪里,所以提供更多而不是更少):
class _EventChatScreenState extends ConsumerState<EventChatScreen> {
FirebaseDatabase dbInstance = FirebaseDatabase.instance;
late TextEditingController _messageFieldController;
late DatabaseReference eventDbRef;
@override
void initState() {
super.initState();
_messageFieldController = TextEditingController();
eventDbRef = dbInstance.ref("none");
}
@override
void dispose() {
_messageFieldController.dispose();
super.dispose();
}
Map<String, ChatMessage> chatMessages = {};
@override
Widget build(BuildContext context) {
final user = ref.watch(userProvider);
final event = ModalRoute.of(context)!.settings.arguments as EventRepository;
if (eventDbRef.path == "none") {
print("IT IS NONE");
eventDbRef = dbInstance.ref("/events/${event.event.eventId}/");
print(eventDbRef.path); // Print's correct value
}
return StreamBuilder(
stream: eventDbRef.onChildAdded,
builder: (context, snapshot) {
if (chatMessages == {}) {
return const Text("Loading...");
}
DatabaseEvent data;
if (snapshot.hasData) {
data = snapshot.data as DatabaseEvent;
ChatMessage newChatMessage = ChatMessage(
chatMessageId: "",
userId: "",
displayname: "",
message: "",
datetime: "",
);
for (var child in data.snapshot.children) {
switch (child.key) {
case "chatMessageId":
newChatMessage.chatMessageId = child.value.toString();
break;
case "userId":
newChatMessage.userId = child.value.toString();
break;
case "displayName":
newChatMessage.displayname = child.value.toString();
break;
case "message":
newChatMessage.message = child.value.toString();
break;
case "datetime":
final datetime = DateTime.parse(child.value.toString());
final DateFormat formatter = DateFormat('h:mm aa');
final String formatted = formatter.format(datetime);
newChatMessage.datetime = formatted;
break;
default:
}
}
if (chatMessages[data.snapshot.key] == null) {
chatMessages[data.snapshot.key!] = newChatMessage;
}
}
return ListView.builder(
itemCount: chatMessages.length,
itemBuilder: (context, index) {
String key = chatMessages.keys.elementAt(index);
if (chatMessages[key]!.userId == user.user.userId) {
return UnconstrainedBox(
alignment: Alignment.centerRight,
child: Container(
margin: const EdgeInsets.symmetric(vertical: 5),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
padding: const EdgeInsets.only(left: 10),
child: Text(chatMessages[key]!.displayname),
),
Container(
padding: const EdgeInsets.symmetric(vertical: 5, horizontal: 15),
decoration: BoxDecoration(
borderRadius: const BorderRadius.all(
Radius.circular(20),
),
color: Theme.of(context).colorScheme.primary,
),
child: Text(chatMessages[key]!.message,
style: TextStyle(
color: Theme.of(context).colorScheme.onPrimary,
),
),
),
Container(
padding: const EdgeInsets.only(left: 10),
child: Text(chatMessages[key]!.datetime),
),
],
),
),
);
}
},
);
},
),
问题是,当用户进入聊天屏幕时,其中一条消息已经出现在聊天中。 我希望什么都没有,因为我没有在任何地方设置任何初始数据,没有使用实时数据库的持久性,也没有使用我自己的本地数据库。
我对 StreamBuilders 的理解是,他们只会在新数据进来时获取新数据,而不是可能已经存在并因此不会通过它发送的数据(即,当发送新的聊天消息时,stream 应该会收到它,这是有效的,但它不应接收数据库中已有的聊天消息消息)。 如果这种理解是错误的,那么尽管数据库中有 2、3、4 等,为什么我只收到一条消息?
也许我理解/使用 StreamBuilders、Firebase 实时数据库,或两者都不正确?
也许您对 streambuilder 的理解是错误的。
假设您使用FutureBuilder
,它会等到未来结束,然后相应地构建小部件,但如果数据库中发生某些变化,它不会再次构建,但对于StreamBuilder
,它基本上会监听(并从中获取初始数据stream,这里是你的db
)到 stream 并在它发生变化或新数据添加到 stream(这里是database
)时构建,它将获取更新的数据并再次构建小部件。
在这里阅读:
https://firebase.flutter.dev/docs/firestore/usage/#realtime-changes
将此eventDbRef.onChildAdded
分配给 initState 中的变量,然后将该变量用作 streambuilder 中的 stream 参数。 在 Streambuilder 中调用 db 会导致它在每次构建小部件树时重新运行。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.