whenComplete() method not working as expected - Flutter Async
In my Flutter app, I am trying to run some code after an async function is completed by using the whenComplete() method. The problem is the code in my whenComplete() method is getting executed even before the async function is finished.
I have tried using the then() method also and that is also producing the same result.
This is the init function in which I am calling that async function:
@override
void initState() {
super.initState();
FirebaseAuth.instance.currentUser().then((user) {
setState(() {
mUid = user.uid;
getUserName();
getUserHomes().whenComplete(() {
print(mUserHomes);
setState(() {
dropdownVal = mUserHomes[0];
});
});
});
}).catchError((e) {
print(e);
});
}
This is the function body for the async function:
Future getUserHomes() async {
CollectionReference ref = Firestore.instance
.collection('users')
.document(mUid)
.collection('accessibleHomes');
QuerySnapshot eventsQuery = await ref.getDocuments();
eventsQuery.documents.forEach((document) {
DocumentReference homeReference = document["homeReference"];
getHomeDevices("home", homeReference).whenComplete(() {
setState(() {});
});
homeReference.get().then((DocumentSnapshot ds) {
mUserHomes.add(ds["alias"].toString());
});
});
}
The console output on running the app is:
Performing hot restart...
Syncing files to device ASUS Z01RD...
Restarted application in 2,521ms.
I/flutter ( 5718): []
E/flutter ( 5718): [ERROR:flutter/lib/ui/ui_dart_state.cc(148)] Unhandled Exception: RangeError (index): Invalid value: Valid value range is empty: 0
E/flutter ( 5718): #0 List.[] (dart:core-patch/growable_array.dart:145:60)
E/flutter ( 5718): #1 _TabOneState.initState.<anonymous closure>.<anonymous closure>.<anonymous closure>.<anonymous closure> (package:smart_switch/home/tabs/tab_one/tab_one_content.dart:52:37)
E/flutter ( 5718): #2 State.setState (package:flutter/src/widgets/framework.dart:1117:30)
E/flutter ( 5718): #3 _TabOneState.initState.<anonymous closure>.<anonymous closure>.<anonymous closure> (package:smart_switch/home/tabs/tab_one/tab_one_content.dart:51:11)
E/flutter ( 5718): #4 _rootRun (dart:async/zone.dart:1120:38)
E/flutter ( 5718): #5 _CustomZone.run (dart:async/zone.dart:1021:19)
E/flutter ( 5718): #6 _FutureListener.handleWhenComplete (dart:async/future_impl.dart:150:18)
E/flutter ( 5718): #7 Future._propagateToListeners.handleWhenCompleteCallback (dart:async/future_impl.dart:609:39)
E/flutter ( 5718): #8 Future._propagateToListeners (dart:async/future_impl.dart:665:37)
E/flutter ( 5718): #9 Future._complete (dart:async/future_impl.dart:473:7)
E/flutter ( 5718): #10 _SyncCompleter.complete (dart:async/future_impl.dart:51:12)
E/flutter ( 5718): #11 _AsyncAwaitCompleter.complete (dart:async-patch/async_patch.dart:28:18)
E/flutter ( 5718): #12 _completeOnAsyncReturn (dart:async-patch/async_patch.dart:294:13)
E/flutter ( 5718): #13 _TabOneState.getUserHomes (package:smart_switch/home/tabs/tab_one/tab_one_content.dart)
E/flutter ( 5718): #14 _asyncThenWrapperHelper.<anonymous closure> (dart:async-patch/async_patch.dart:77:64)
E/flutter ( 5718): #15 _rootRunUnary (dart:async/zone.dart:1132:38)
E/flutter ( 5718): #16 _CustomZone.runUnary (dart:async/zone.dart:1029:19)
E/flutter ( 5718): #17 _FutureListener.handleValue (dart:async/future_impl.dart:126:18)
E/flutter ( 5718): #18 Future._propagateToListeners.handleValueCallback (dart:async/future_impl.dart:639:45)
E/flutter ( 5718): #19 Future._propagateToListeners (dart:async/future_impl.dart:668:32)
E/flutter ( 5718): #20 Future._complete (dart:async/future_impl.dart:473:7)
E/flutter ( 5718): #21 _SyncCompleter.complete (dart:async/future_impl.dart:51:12)
E/flutter ( 5718): #22 _AsyncAwaitCompleter.complete (dart:async-patch/async_patch.dart:28:18)
E/flutter ( 5718): #23 _completeOnAsyncReturn (dart:async-patch/async_patch.dart:294:13)
E/flutter ( 5718): #24 Query.getDocuments (package:cloud_firestore/src/query.dart)
E/flutter ( 5718): #25 _asyncThenWrapperHelper.<anonymous closure> (dart:async-patch/async_patch.dart:77:64)
E/flutter ( 5718): #26 _rootRunUnary (dart:async/zone.dart:1132:38)
E/flutter ( 5718): #27 _CustomZone.runUnary (dart:async/zone.dart:1029:19)
E/flutter ( 5718): #28 _FutureListener.handleValue (dart:async/future_impl.dart:126:18)
E/flutter ( 5718): #29 Future._propagateToListeners.handleValueCallback (dart:async/future_impl.dart:639:45)
E/flutter ( 5718): #30 Future._propagateToListeners (dart:async/future_impl.dart:668:32)
E/flutter ( 5718): #31 Future._complete (dart:async/future_impl.dart:473:7)
E/flutter ( 5718): #32 _SyncCompleter.complete (dart:async/future_impl.dart:51:12)
E/flutter ( 5718): #33 _AsyncAwaitCompleter.complete (dart:async-patch/async_patch.dart:28:18)
E/flutter ( 5718): #34 _completeOnAsyncReturn (dart:async-patch/async_patch.dart:294:13)
E/flutter ( 5718): #35 MethodChannel.invokeMapMethod (package:flutter/src/services/platform_channel.dart)
E/flutter ( 5718): #36 _asyncThenWrapperHelper.<anonymous closure> (dart:async-patch/async_patch.dart:77:64)
E/flutter ( 5718): #37 _rootRunUnary (dart:async/zone.dart:1132:38)
E/flutter ( 5718): #38 _CustomZone.runUnary (dart:async/zone.dart:1029:19)
E/flutter ( 5718): #39 _FutureListener.handleValue (dart:async/future_impl.dart:126:18)
E/flutter ( 5718): #40 Future._propagateToListeners.handleValueCallback (dart:async/future_impl.dart:639:45)
E/flutter ( 5718): #41 Future._propagateToListeners (dart:async/future_impl.dart:668:32)
E/flutter ( 5718): #42 Future._complete (dart:async/future_impl.dart:473:7)
E/flutter ( 5718): #43 _SyncCompleter.complete (dart:async/future_impl.dart:51:12)
E/flutter ( 5718): #44 _AsyncAwaitCompleter.complete (dart:async-patch/async_patch.dart:28:18)
E/flutter ( 5718): #45 _completeOnAsyncReturn (dart:async-patch/async_patch.dart:294:13)
E/flutter ( 5718): #46 MethodChannel.invokeMethod (package:flutter/src/services/platform_channel.dart)
E/flutter ( 5718): #47 _asyncThenWrapperHelper.<anonymous closure> (dart:async-patch/async_patch.dart:77:64)
E/flutter ( 5718): #48 _rootRunUnary (dart:async/zone.dart:1132:38)
E/flutter ( 5718): #49 _CustomZone.runUnary (dart:async/zone.dart:1029:19)
E/flutter ( 5718): #50 _FutureListener.handleValue (dart:async/future_impl.dart:126
So in the init() function where I am calling the async function getUserHomes I am trying to set the dropdownVal variable to the first value of the list mUserHomes which is fetched from Firestore DB. The list is printed as [] in the console which means empty and but if I print the list in later stages it is getting printed with the values.
Solution 1:
Your getUserHomes
function does a bunch of asynchronous work in the foreach
callback that it doesn't wait for, so getUserHomes
completes its returned Future
almost immediately after ref.getDocuments
finishes.
If you want to wait for all work in getUserHomes
to finish, you could do something like:
Future<void> getUserHomes() async {
CollectionReference ref = Firestore.instance
.collection('users')
.document(mUid)
.collection('accessibleHomes');
QuerySnapshot eventsQuery = await ref.getDocuments();
final waitList = <Future<void>>[];
for (var document in eventsQuery.documents) {
DocumentReference homeReference = document["homeReference"];
waitList.add(getHomeDevices("home", homeReference));
waitList.add(
homeReference.get().then((DocumentSnapshot ds) {
mUserHomes.add(ds["alias"].toString());
});
);
}
await Future.wait(waitList);
}