• 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 Firestore object initialization final FirebaseFirestore _firestore = FirebaseFirestore.instance;

  • 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.


Solution 1: 2IIZ

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(),
    );
}


Solution 2: jamesdlin

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.