Search code examples
firebasefluttergoogle-cloud-firestorestream-builder

Nesting two stream builders causing bad state error


I am fetching data from two different firestore collections and this is my code

 StreamBuilder(
           stream: Firestore.instance.collection('items').snapshots(),
           builder: (BuildContext context, snapshot){

             if(snapshot.connectionState == ConnectionState.waiting){
               return CupertinoActivityIndicator();
             }
             if(snapshot.data != null){
               return ListView.builder(
                 itemCount: snapshot.data.documents.length,
                 itemBuilder: (context,index){
                   return Column(
                     children: <Widget>[

                       Text(snapshot.data.documents[index]['name']),
                       Text(snapshot.data.documents[index]['color']),
                       Text(snapshot.data.documents[index]['lifetime']),

                       Container(
                         child: StreamBuilder(
                           stream: Firestore.instance.collection('users')
                            .document(userid).collection('Quantity')
                            .document(snapshot.data.documents[index]['id']).snapshots(),
                           builder: (BuildContext context, snap){

                             if(snapshot.connectionState == ConnectionState.waiting){
                              return CupertinoActivityIndicator();
                            }
                            if(snap.data != null){
                              return Container(
                              child:  Text(snap.data.documents.length)
                              );
                            }
                           },
                         ),
                       )

                     ],
                   );
                 });
             }
           },
         )

It is giving me error but when I use futurebuilder inside streambuilder everything works fine and I also used stream broadcast but it is also giving me same error. Here is the code which I used for broadcast stream

  StreamController _controller = StreamController.broadcast();
        Stream getItems() async*{
          Firestore.instance.collection('items').snapshots().listen((data){
            _controller.add(data);
          })
          yield* _controller.stream;
        }

This is the error I am getting


Solution

  • You shouldn't create a new Stream inside the StreamBuilder. When you do:

    StreamBuilder(
      stream: Firestore.instance.collection('items').snapshots(),
    

    And

    StreamBuilder(
      stream: Firestore.instance.collection('users')
        .document(userid).collection('Quantity')
        .document(snapshot.data.documents[index]['id']).snapshots(),
    

    Each time your build() function is called a new StreamBuilder is created, so Firestore.instance.collection()...snapshots() is called, returning a new Stream each time.

    You should convert your widget to a StatefulWidget and initialize your Stream on initState(), passing it as a class variable to your StreamBuilder. The nested StreamBuilder can also be transformed into a StatefulWidget and created in place, but initialized on the same manner. Just pay attention that you might need a Key for showing it correctly on a ListView.

    Also if you want to convert a Single Subscription Stream to a Broadcast Stream you just have to call asBroadcastStream to convert it.