I'm trying to keep everything modular and I stumbled onto a problem. I want to keep all code related to Firebase Realtime Database and Firebase Cloud Storage in my message_dao
widget, so I have my receivedChats
widget calling a message_dao
function that activates the listener. However, it looks like receivedChats
is receiving an empty list because when I print out the chats
variable it's empty.
message_dao
Future<List> activateChatListener() async {
var msg;
_receivedChatsStream = _messagesRef.onValue.listen((event) {
event.snapshot.children.forEach((snapshot) {
dataList.add(snapshot.value);
});
//Some other code that returns a future
});
return dataList;
}
receivedChats
class _ReceivedChatsState extends State<ReceivedChats> {
var chats = [];
@override
void initState() {
super.initState();
loadChats();
}
Future<void> loadChats() async {
var dataList = await messageDao.activateChatListener();
setState(() {
chats = dataList;
});
print('chats: ' chats.toString()) //This shows an empty list
}
//...other code...
}
CodePudding user response:
You are returning the listbefore the api has finished fetching data
Try this instead
Future<List> activateChatListener() async {
var msg;
_receivedChatsStream = _messagesRef.onValue.listen((event) {
event.snapshot.children.forEach((snapshot) {
dataList.add(snapshot.value);
});
//Some other code that returns a future
return dataList;
});
}
CodePudding user response:
Because your loadChats
will be called once. Instead of storing your data into dataList
array, you can directly use that snapshot through StreamBuilder
Example:
class NoteList extends StatelessWidget {
final db = FirebaseFirestore.instance;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Notes"),
centerTitle: true,
),
body: StreamBuilder<QuerySnapshot>(
stream: db.collection('notes').snapshots(),
builder: (context, snapshot) {
if (!snapshot.hasData) {
return Center(
child: CircularProgressIndicator(),
);
} else
return ListView(
children: snapshot.data.docs.map((doc) {
return Card(
child: ListTile(
title: Text(doc.data()['title']),
),
);
}).toList(),
);
},
),
);
}
}
Here is the full example that you can refer and you can solve your problem.