流构建器在不应该有数据的时候有数据



我使用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的理解是,他们只获得新数据,因为它进来,而不是可能已经存在的数据,因此不通过它发送(即。当发送新的聊天消息时,流应该接收它(这可以工作,但它不应该接收数据库中已经存在的聊天消息)。如果这种理解是错误的,那么为什么我只得到一个消息,尽管有2,3,4等在数据库中?

也许我理解/使用StreamBuilders, Firebase实时数据库,或两者都不正确?

也许你对streambuilder的理解是错误的。

假设你使用FutureBuilder,它会等到未来结束,然后相应地构建小部件,但如果数据库发生变化,它不会再次构建,但对于StreamBuilder,它基本上会监听(并从流中获取初始数据,这里是你的db)到流并构建每当它改变或新数据被添加到流(这里是database)时,它会获得更新的数据并再次构建小部件。


https://firebase.flutter.dev/docs/firestore/usage/#realtime-changes

将此eventDbRef.onChildAdded分配给initState中的变量,然后使用该变量作为streambuilder中的流参数。在Streambuilder中调用db会导致每次构建小部件树时都重新运行它。

相关内容

最新更新