How can I wait until Firebase Database data is retrieved in Flutter?

157

Solution 1

A listener is something that waits for changes (new documents added etc.) and notifies you whenever that happens. So it isn't something that starts/ends after you call it - you typically create it in the init of your Flutter class, and it changes state whenever something changes.

It looks like you want to grab all the users, once, and not listen like you're currently doing.

So instead of listening, perhaps just read the data. Something like:

// fetch all the documents
final allDocs =
        await FirebaseFirestore.instance.collection('users').get();
// map them to something like your strings.
final thedetails = allDocs.docs.map((DocumentSnapshot e) => e.data()!.toString()).toList();
return thedetails;

Solution 2

A really good way to learn and understand how Firebase works with flutter is FlutterFire, as you are dealing with future result you should use any state management to control at first if it is complete or not and then consider that return a promise and the way you manage that is different. This is an example for Future use as described in FlutterFire Cloud Firestore documentation:

class GetUserName extends StatelessWidget {
  final String documentId;

  GetUserName(this.documentId);

  @override
  Widget build(BuildContext context) {
    CollectionReference users = FirebaseFirestore.instance.collection('users');

    return FutureBuilder<DocumentSnapshot>(
      future: users.doc(documentId).get(),
      builder:
          (BuildContext context, AsyncSnapshot<DocumentSnapshot> snapshot) {

        if (snapshot.hasError) {
          return Text("Something went wrong");
        }

        if (snapshot.hasData && !snapshot.data!.exists) {
          return Text("Document does not exist");
        }

        if (snapshot.connectionState == ConnectionState.done) {
          Map<String, dynamic> data = snapshot.data!.data() as Map<String, dynamic>;
          return Text("Full Name: ${data['full_name']} ${data['last_name']}");
        }

        return Text("loading");
      },
    );
  }
}

But if you just need to load once in a sync way the answer from Jon Mountjoy is the right one.

Share:
157
Luca Orlandi
Author by

Luca Orlandi

Updated on January 04, 2023

Comments

  • Luca Orlandi
    Luca Orlandi over 1 year

    I am using flutter and I have a simple method that reads each user present in my database and adds them to a list, once finished reading the users, the method must return the list containing all the data read, my problem is that my function does not wait that the Listener has finished reading and then returns my list (myList) even before the Listener has finished reading. How can I wait for the return myList until the Listener has read all the elements?

    Here's the code:

    Future<List<String>> getUsers () async {
    
      List<String> myList = [];
    
      final mRef = FirebaseDatabase.instance.ref().child("Users");
    
      mRef.onValue.listen((event) async {
        for (final child in event.snapshot.children) {
    
          myList.add( child.value.toString() );  //ADDS THE VALUE TO THE LIST
    
        }
      });
    
      //RETURN THE LIST
      return myList;
    
    }
    

    I tried to put an await in front of my Listener but nothing worked.

  • Luca Orlandi
    Luca Orlandi about 2 years
    thanks a lot, but how can I do this using the Realtime Database? (Not Firestore)