skip to Main Content

Firstly, I’m sorry if this has been answered prior, I have scoured the web for answers and while I’ve gained bits and pieces here and there I’m still left dumbfounded.

My current code is as follows:

  @override
  Widget build(BuildContext context) {
    // this bit is getting the Ids
    CollectionReference _collectionRef =
        FirebaseFirestore.instance.collection('Standard_Questions');

    Future<List> getData() async {
      // Get docs from collection reference
      QuerySnapshot querySnapshot = await _collectionRef.get();

      // Get data from docs and convert map to List
      final allData = querySnapshot.docs.map((doc) {
        Map<String, dynamic> data = doc.data() as Map<String, dynamic>;
        return {
          'documentId': doc.id,
          ...data,
        };
      }).toList();

      print(allData);
      return allData;
    }


    final b = getData();
    print(b);
    print('here');

Now, my intent has been to pull from my firestore database once, store the information in a list and then pass it on to the next screen. However, I seem to be lost/confused. My understanding has been that async + await should allow you to execute an action, wait for it to finish, then assign the returned value to a variable in the function. As such, I’d have liked to think that this code is setup to do just that – make a connection to firebase, wait for it to return the collection reference, assign the data to a list, then return the list. However, this has not been the case, instead I am constantly being returned a Future<list> rather than a list. The bottom print commands are an attempt to understand what is going on, they print :

I/flutter (21131): Instance of 'Future<List<dynamic>>'
I/flutter (21131): here
I/flutter (21131): Future<List<dynamic>>
I/flutter (21131): Instance of 'Future<List<dynamic>>'
I/flutter (21131): here
I/flutter (21131): Future<List<dynamic>>
I/flutter (21131): [{documentId: Question0, Text: N/A, Audio: N/A}, {documentId: Question1, Text: This is Question 1, Audio: audio_link}]

Which indicates to me a) it is not waiting for the information to come back, and b) it’s running the print statement too many times, although the latter issue isn’t something I’m focussing on now, I mention it as a possible point of problem. If anyone could please explain to me where my understanding has failed and what a correct approach here would be I would much appreciate it. I have looked at FutureBuilders and StreamBuilders but I do not think either fit my use case. I do not want to display the information on the screen I am loading them in, I want to use them for other purposes and do not want a constant pulling on the database.

2

Answers


  1. Chosen as BEST ANSWER

    My answer to this issues is as follows:

    class _NameInput extends State<NameInput> {
      List allData = [];
    
      @override
      void initState() {
        super.initState();
        _getData();
      }
    
      Future<void> _getData() async {
        CollectionReference _collectionRef =
            FirebaseFirestore.instance.collection('Standard_Questions');
    
        QuerySnapshot querySnapshot = await _collectionRef.get();
        allData.addAll(querySnapshot.docs.map((doc) {
          Map<String, dynamic> data = doc.data() as Map<String, dynamic>;
          return {
            'documentId': doc.id,
            ...data,
          };
        }).toList());
      }
    

    My understanding is as follows: Upon loading of the page the initialization of the page now includes running the _getData() function which will return the values required from firebase. Prior comment from @BouncyBits regarding why it was in the Build widget made me question the same, I am still new to dart and had poorly approached the task. Also thank you to @jamesdlin for pointing out similar issues with it being in the build widget - I have in fact looked at FutureBuilders as a use case here prior however it didn't suit my use case. Hopefully this little bit of code will help someone in a similar predicament.


  2. Your getData is an async function, so it returns a Future. If you want to unwrap the value from that Future, you need to use either then or (if you’re in a context where that is allowed) await.

    So either:

    getData().then((b) {
      print(b);
      print('here');
    }
    

    Or:

    final b = await getData();
    print(b);
    print('here');
    

    As jamesdlin commented, if you want to show b in your UI, you can handle its asynchronous nature either by adding it to the state of your widget in a setState() call, or use a FutureBuilder.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search