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
My answer to this issues is as follows:
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.
Your
getData
is anasync
function, so it returns aFuture
. If you want to unwrap the value from thatFuture
, you need to use eitherthen
or (if you’re in a context where that is allowed)await
.So either:
Or:
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 asetState()
call, or use aFutureBuilder
.