0

I have a StreamBuilder that isn't displaying a CircularProgressIndicator when waiting for the results from the Firebase connection. I just end up receiving a generic Null check operator used on a null value error because of the dirty state. The error disappears once the connection is established and the snapshot is returned.

StreamBuilder(
          stream: FirebaseFirestore.instance.collection('posts').snapshots(),
          builder: (context,
              AsyncSnapshot<QuerySnapshot<Map<String, dynamic>>> snapshot) {
            if (snapshot.connectionState == ConnectionState.waiting) {
              return const Center(
                child: CircularProgressIndicator(),
              );
            }
            return ListView.builder(
              itemCount: snapshot.data!.docs.length,
              itemBuilder: (context, index) => PostCard(
                snap: snapshot.data!.docs[index].data(),
              ),
            );
          }),

Why doesn't it render the CircularProgressIndicator if Connection.State == waiting?

As replied in comments below. I am receiving the error:

Could not reach Cloud Firestore backend. Backend didn't respond within 10 seconds This typically indicates that your device does not have a healthy Internet connection at the moment. The client will operate in offline mode until it is able to successfully connect to the backend.

Running on Android Emulator and the connection is stable/fast so not sure why it's happening.

Milie
  • 374
  • 1
  • 6
  • 22

1 Answers1

1

Firestore snapshots, when loading new ones, are so quick you almost never will see the CircularProgressIndicator.

Furthermore, you're using a else clause that includes any other case. What happens is that when the code reaches this line:

itemCount: snapshot.data!.docs.length,

data is null and therefore you've got yourself a null check error.

Try the following:

final a = StreamBuilder(
  stream: FirebaseFirestore.instance.collection('posts').snapshots(),
  builder: (context, snapshot) {
    if (snapshot.connectionState == ConnectionState.waiting) {
      return const Center(child: CircularProgressIndicator());
    }

    if (snapshot.hasData) {
      return ListView.builder(
        itemCount: snapshot.data!.docs.length,
        itemBuilder: (context, index) => PostCard(
          snap: snapshot.data!.docs[index].data(),
        ),
      );
    }

    // TODO properly handle error cases
    print(snapshot.stackTrace);
    print(snapshot.error);
    return const Text('Something went wrong');
  },
);

When you'll try this there's a good chance you'll see Something went wrong: you need to investigate why your snapshots haven't got data.

venir
  • 1,809
  • 7
  • 19
  • Sorry, the `else` clause was added afterwards while testing. Code has been edited to show results. Now receiving: `Could not reach Cloud Firestore backend. Backend didn't respond within 10 seconds. This typically indicates that your device does not have a healthy Internet connection at the moment. The client will operate in offline mode until it is able to successfully connect to the backend.` – Milie Aug 12 '22 at 16:42
  • 1
    As I wrote in my answer, indeed you need to investigate the error underneath. In your case, there's an internet connection problem. Furthermore, in your edited code you still aren't checking `snapshot.hasData`. This *will* lead to errors. – venir Aug 12 '22 at 16:47
  • I used your code but received the same error. Constantly, every 10 seconds : `[WatchStream]: (f9eedfa) Stream closed with status: Status{code=UNAVAILABLE, description=Channel shutdownNow invoked, cause=null}.` So definitely a connection error. It probably has to do with the emulator's connection. Thanks for the error handling correction. – Milie Aug 12 '22 at 16:56
  • If you're using an Android emulator there's a good chance you need to give internet permissions. Considering accepting and upvoting my answer if it's useful. – venir Aug 12 '22 at 16:57
  • 1
    Also check this: https://stackoverflow.com/a/55606098/15831316 – venir Aug 12 '22 at 16:57
  • 1
    Same issue but most probably an emulator issue. Will test on a device later, hopefully solves the problem. Thanks again – Milie Aug 12 '22 at 17:02
  • 2
    DON'T DO THIS: `stream: FirebaseFirestore.instance.collection('posts').snapshots()`. Never create your stream as the stream parameter to a StreamBuilder. For details, look at the first two paragraphs of FutureBuilder docs, or watch this video: https://www.youtube.com/watch?v=sqE-J8YJnpg – Randal Schwartz Aug 12 '22 at 20:04
  • 1
    @RandalSchwartz yes, this must be taking into account, but I thought it was out of scope. @milie if you leave your `stream` like that you'll be charged for several reads every time this widget rebuilds. Use a `StatefulWidget` with a `initState` implementation to handle this. – venir Aug 12 '22 at 20:22
  • 1
    I flag the "stream in stream" and "future in future" violations every time I see them now. It's starting to be a bad meme. – Randal Schwartz Aug 13 '22 at 01:19