2

I been trying to figure this out for the entire weekend so I finaly decided to ask you for your advice.

Got a streambuilder which listens for a stream or recipes (filtered by the category -> soups, deserts etc.).

I were confused because the Text "Nothing" (last return statement) was the only thing showing, even though my print statements in the if condition, which asks for the connectionstate.active shows me all the values.

When I print the connection state out one line above my text widget "Nothing" I get "active".

Of course I could just get rid of my if statement and put the returning widget at the end, but I would like to know and understand, why my return statement in my .active condition does not show me the column etc. even though the print statements are shown in the console.

Btw I saw alot of other resources were a Listview is used but I am not sure weather or not I can use a Listview together with a stack (because I want to show data on top of each other).

Looking forward to your replys!

Regards Thomas

new StreamBuilder<QuerySnapshot>(
                    stream: FirebaseFirestore.instance.collection("rezepte").where("kategorie", isEqualTo: ausgewaehlteKategorie).snapshots(),
                    builder: (context, AsyncSnapshot<QuerySnapshot> snapshot){
                      print("***** STREAMBUILDER *****");
                      if (snapshot.connectionState == ConnectionState.waiting) {
                        print(snapshot.connectionState);
                        return CircularProgressIndicator();
                      }
                      
                      if(snapshot.connectionState == ConnectionState.active){
                        print(snapshot.connectionState);
                        print(snapshot.data!.docs);
                        print(snapshot.data!.docs[0]["name"]);
                        print(snapshot.data!.docs[0]["kategorie"]);

                        print(snapshot.data!.docs.length);

                        snapshot.data!.docs.map((docs){
                          print("Test1");
                          listeAllerRezepte.add(
                            Rezept(
                              name: docs["name"].toString(),
                              kategorie: docs["kategorie"].toString(),
                              naehrwertKohlenhydrate: docs["naehrwertKohlenhydrate"],
                              naehrwertFett: docs["naehrwertFett"],
                              naehrwertEiweiss: docs["naehrwertEiweiss"],
                              naehrwertKohlenhydrateProzent: double.parse((100 / (docs["naehrwertKohlenhydrate"] + docs["naehrwertFett"] + docs["naehrwertEiweiss"]) * docs["naehrwertKohlenhydrate"]).toStringAsFixed(2)),
                              naehrwertFettProzent: double.parse((100 / (docs["naehrwertKohlenhydrate"] + docs["naehrwertFett"] + docs["naehrwertEiweiss"]) * docs["naehrwertFett"]).toStringAsFixed(2)),
                              naehrwertEiweissProzent: double.parse((100 / (docs["naehrwertKohlenhydrate"] + docs["naehrwertFett"] + docs["naehrwertEiweiss"]) * docs["naehrwertEiweiss"]).toStringAsFixed(2)),
                              img: docs["img"],
                              favorit: docs["favorit"]
                            )
                          );
                          print("Test2");

                          print(listeAllerRezepte[0]);
                          print(listeAllerRezepte[0].name.toString());
                          print(listeAllerRezepte[0].kategorie.toString());
                          print(listeAllerRezepte[0].img.toString());

                          return new Column(
                            children: [
                              new Stack(
                                alignment: Alignment.bottomCenter,
                                children: [
                                  new Text("Test1"),
                                  new Container(
                                    child: new GestureDetector(
                                      child: new Column(
                                        children: [
                                          new Text("TEST"),
                                          new Image(
                                            image: (docs["img"].toString().length > 0) ? NetworkImage(docs["img"].toString()) : NetworkImage(globals.listeAllerKategorien![nummerAusgewaehleKategorie].img.toString())
                                          ),
                                        ],
                                      ),
                                      onTap: () {
                                      },
                                    ),
                                  ),
                                  new Divider(height: 100.0)
                                ],
                              ),
                              new Divider(height: 15.0)
                            ]
                          );
                        }).toList();
                      }

                      if(snapshot.connectionState == ConnectionState.done){
                        print(snapshot.connectionState);
                      }
                      
                      if(!snapshot.hasData){
                        return Text("Loading");
                      }

                      return new Text("Nothing");
                    }
                  )
Goku
  • 49
  • 7

1 Answers1

3

Once the StreamBuilder has recieved all of the data and a done signal, the state becomes done. It does not sit there in there in active. Your checks should go is waiting, has data, and a catch all afterwards for no data.

UPDATE: The issue is in your return statement in the if(snapshot.connectionState == ConnectionState.active) block. You are not actually returning a widget from the block, so the function is continuing until it reaches the final return statement.

First, make this if statement if(snaphsot.hasData). Then take a look at this section:

snapshot.data!.docs.map((docs){
  ...
  return new Column(
  ...
}

Here, your return statement is to the anonymous function passed to the map method. The Columns are not being returned out of the builder.

While I am not quite sure what your needs are, I believe some of your widgets are nested improperly as well. Below is my best guess at what you are going for, please adjust accordingly. (I have left out some of your code for brevity, focusing only on building the widgets causing your issues.)

if(snapshot.hasData){
  return new Column(
    children: snapshot.data!.docs.map((docs){
      return new Stack(
       alignment: Alignment.bottomCenter,
       children: [
         new Text("Test1"),
         new Container(
           child: new GestureDetector(
             child: new Column(
               children: [
                 new Text("TEST"),
                 new Image(
                   image: (docs["img"].toString().length > 0) ? NetworkImage(docs["img"].toString()) : NetworkImage(globals.listeAllerKategorien![nummerAusgewaehleKategorie].img.toString())
                 ),
               ],
             ),
             onTap: () {},
           ),
         ),
         new Divider(height: 100.0)
       ],
     );
   },
 );
}

NOTE: A ListView is certainly capable of providing what you need, and it is a much better option than Column. It provides scrolling out of the box, better performance and memory usage, as well as some handy constructors that can provide a Divider where needed. I encourage you to check it out once you are comfortable with these results.

Lee3
  • 2,882
  • 1
  • 11
  • 19
  • Hi Lee3, thank you for your reply. That is what confuses me. I just changed it to if(snapshot.hasData), but now, again, like before, only "Nothing" shows. I also tried to set the condition to "snapshot.hasData or snapshot.connectionstate done", but that did not work either. – Goku Feb 06 '22 at 20:48
  • I even tried snapshot.connectionstate != connectionstate.waiting (which should always be the case but when there is no data). Even in that case, the "Nothing" Fallback is shown. Seems like I did not quiet understand something certain yet. It seems like, the more acurate my conditions become, the further I am away from the solution :D – Goku Feb 06 '22 at 21:03
  • I did not have a chance to really dig into your code before my original response. I have now pinpointed the problem. Please check out my updated answer. – Lee3 Feb 07 '22 at 05:01
  • Thank you! As you mentioned, I have/hda to return the data I get from the database "one level" above (within the closure of the if statement, not within the closure of the .map method). Works now! – Goku Feb 07 '22 at 21:13