I encountered this problem while working with Flutter & Firebase (firestore), I did my research and couldn`t find anything helpful.
I want to turn my streams I get from firestore into a stream of widgets
StreamBuilder()
Here is the method where I try to get my data from firestore as a stream
void messagesStream() async { await for (var snapshot in _firestore.collection('message').snapshots()) { for (var message in snapshot.docs) { print(message.data()); } } }
Here is StreamBuilder widget insdie my widget tree =>
StreamBuilder<QuerySnapshot>(
stream: _firestore.collection('message').snapshots(),
builder: (context, snapshot) {
if (!snapshot.hasData) {
return const Center(
child: CircularProgressIndicator(),
);
}
final messages = snapshot.data!;
List<Text> messageWidgets = [];
for (var message in messages) // <== I get My error here
*// The type 'QuerySnapshot<Object?>' used in the 'for' loop must
// implement Iterable.*
{
final messageText = message.data['text'];
final messageSender = message.data['sender'];
final messageWidget =
Text('$messageText from @$messageSender');
messageWidgets.add(messageWidget);
}
return Column(
children: messageWidgets,
);
},
),
- If I removed the null check operator from
final messages = snapshot.data;
I get a different error which is
A nullable expression can't be used as an iterator in a for-in loop. Try checking that the value isn't 'null' before using it as an iterator.
Edit: Solved the issue, will put the solution here in case anyone encountered the same issue in the future
The problem arised from this exact line
final messageText = message.data['text'];
exactly from the snapshot object.data
According to the cloud_firestore plugin github:
/// A [DocumentSnapshot] contains data read from a document in your [FirebaseFirestore] /// database. /// /// The data can be extracted with the data property or by using subscript /// syntax to access a specific field.
it basically says you can extract data from your database either through the .data
object or by using subscript ['Your-Field]
- just remove
.data
final messageText = message['text'];
CodePudding user response:
I think you may check if "snapshot.data" is not null before anything else.
// This basically means that if you have data, you show the widget CircularProgressIndicator()
if (snapshot.hasData) {
return const Center(
child: CircularProgressIndicator(),
);
}
You may try like this :
// Means that if the snapshot hasn't data show the widget
if (!snapshot.hasData) {
return const Center(
child: CircularProgressIndicator(),
);
}
CodePudding user response:
One way to easily deal with nullable iterables in a for
loop is to use ??
to provide a non-nullable fallback value. For example:
List<int>? nullableList;
for (var element in nullableList ?? <int>[]) {
...
}
Alternatively you can use the conditional-member-access operator with forEach
:
List<int>? nullableList;
nullableList?.forEach((element) {
...
});
although generally I recommend normal for
loops over forEach
.