I am attempting to populate a ListView.builder with data from multiple nodes from my instance of Firebase Realtime Database.
I am interested in listening to changes on the chats
node (and updating the listview when they occur), but less interested in real-time updates on the chats-details
node.
chats
-- 'chat1'
---- 'keyA' : 'This is some text'
---- 'keyB' : 'This is some text'
-- 'chat2'
---- 'keyA' : 'This is some text'
---- 'keyB' : 'This is some text'
chats-details
-- 'chat1'
---- 'keyC' : 'This is some text'
---- 'keyD' : 'This is some text'
-- 'chat2'
---- 'keyC' : 'This is some text'
---- 'keyD' : 'This is some text'
Ideally, all data for chat1, chat2...etc would be appended to Object (myChats
in example below) and fed into the ListView.
Any help would be greatly appreciated. My current code is below. This code currently does not automatically populate the ListView.
// Node 1 - Listen to changes
chatsRef = FirebaseDatabase().reference().child('chats');
// Node 2 - Update when node 1 is updated
chatsDetailsRef = FirebaseDatabase().reference().child('chats-details');
@override
Widget build(BuildContext context) {
List<Chats> myChats = [];
return Scaffold(
appBar: AppBar(),
body: StreamBuilder(
stream: chatsRef.onValue,
builder: (context, snap) {
if (snap.hasData && !snap.hasError && snap.data.snapshot.value != null) {
Map data = snap.data.snapshot.value;
data.forEach((index, data) {
chatsDetailsRef.child(index).once().then((DataSnapshot snapshot) {
Chats currentChat = Chats.fromMap(data);
if (snapshot.value == null) {
Chat emptyChatDetails = Chat();
currentChat.chatDetails = emptyChatDetails;
} else {
Chat foundChatDetails = ChatDetails.fromMap(snapshot.value);
currentChat.chatDetails = foundChatDetails;
}
myChats.add(currentChat);
});
});
return ListView.builder(
itemCount: myChats.length,
itemBuilder: (context, index) {
return ListTile(
title: Text(myChats[index].title),
subtitle: Text(myChats[index].chatDetails.detail),
);
},
);
} else {
return Center(child: Text("No data"));
}
},
),
);
}
}