0

I need to wait my function to be done in a ListView because of a Firestore request. I tried using Future.wait() but it does not work.

FutureBuilder<QuerySnapshot>(
                    future: FirebaseFirestore.instance
                        .collection('Statements')
                        .where('userID',isEqualTo: context.watch<User>().uid)
                        .get(),
                    builder: (BuildContext context, AsyncSnapshot<QuerySnapshot> snapshot){
                      if (snapshot.hasError) {return Text("Erreur");}
                      if (snapshot.connectionState == ConnectionState.waiting) {
                        return Text("Loading");}
                      return Expanded(
                        child:ListView.builder(
                          itemCount: snapshot.data.docs.length,
                            itemBuilder: (context, index) {
                              DocumentSnapshot document = snapshot.data.docs[index];
                              Future.wait([getStatementData(document)]);
                              return StatementCard(statement:selectedStatement,
                                           accommodation : relatedAccommodation,
                                           owner : relatedOwner);
                            },
                        )

Here is the function called :

Future getStatementData(document)  async {

    selectedStatement = Statement.fromFirebase(document);

    document.data()["accommodation"].get().then((value) {
      relatedAccommodation = Accommodation.fromFirebase(value);});

     await FirebaseFirestore.instance
         .collection('Owners')
         .doc(document["ownerList"][0])
         .get().then((value) {
           print(value.data());
           relatedOwner = Owner.fromFirebase(value);
     });

  }

Should I use another future builder ?

2 Answers2

0

You should do it like this by returning another Future Builder inside :

   ListView.builder(
          itemCount: snapshot.data.docs.length,
          itemBuilder: (context, index) {
         DocumentSnapshot document = snapshot.data.docs[index];
        return  FutureBuilder(
      future: getStatementData(document) ,
      builder: (context, snapshot) {
        return snapshot.connectionState == ConnectionState.done
               ? StatementCard(statement:selectedStatement,
                accommodation : relatedAccommodation,
                 owner : relatedOwner);
               : Container(); 
    );
      },
         )

Fahmi Sawalha
  • 682
  • 6
  • 19
0

I think you just missed a simple thing, FutureBuilder also has a connectionstate.done state which you can access. This waits until your future function is Done.

return FutureBuilder(
            future: yourFunction,
            builder: (context, snapshot) {
              switch (snapshot.connectionState) {
                case ConnectionState.none:
                  return Center(child: Text('No status',);
                  break;
                case ConnectionState.waiting:
                  return Center(child: CircularProgressIndicator());
                  break;
                case ConnectionState.done:
                return Text('Im done!') // Your listviewbuilder comes here
                  break;
                default:
              }
            }, 
          ),

doc: https://api.flutter.dev/flutter/widgets/FutureBuilder-class.html example FutureBuilder with ListViewBuilder: https://medium.com/nonstopio/flutter-future-builder-with-list-view-builder-d7212314e8c9

[...]connectionState.done = [future] is not null, and has completed. If the future completed successfully, the [AsyncSnapshot.data] will be set to the value to which the future completed. If it completed with an error, [AsyncSnapshot.hasError] will be true and [AsyncSnapshot.error] will be set to the error object.[...]

Marcel Dz
  • 2,321
  • 4
  • 14
  • 49