Flutter Async Load Multiple Functions One After The Other
Solution 1
It seems like the
load()
function itself completes before theloadFeed()
Future is finished, how can I fix that?
That's exactly what's wrong. You do:
load(int categoryIndex, String _url) async {
loadFeed(_url).then((result) {
// ... bunch of code...
});
}
Your load
function calls loadFeed
, registers a Future.then
callback, ignores the newly returned Future
, and synchronously returns to the caller after callback registration. It does not use await
to wait for the Future
to complete, nor does it return the Future
to the caller to allow the caller to wait for the Future
.
It's much simpler if you use async
/await
instead of mixing it with the raw Future
API:
Future<void> load(int categoryIndex, String _url) async {
var result = await loadFeed(_url);
// ... bunch of code...
}
Additionally, enabling the unawaited_futures
lint in your analysis_options.yaml
file would have caught this problem during static analysis.
Solution 2
In future functions, you can use whencomplete
, from the documentation:
"WhenComplete", Registers a function to be called when this future completes.
The [action] function is called when this future completes, whether it does so with a value or with an error.
This is the asynchronous equivalent of a "finally" block.
-
Change
load
into a future function, and add a return value to let dart know that you are done, like this:Future load(int categoryIndex, String _url) async { loadFeed(_url).then((result) { if (null == result || result.toString().isEmpty) { print("error"); return; } data.value = [[],[],[],]; for (var i = 0; i < result.items.length; i++) { data.value[categoryIndex].add(result.items[i]); } return data.notifyListeners(); //add a return here, to tell dart that this function is done. }); }
-
Change your
loadAll
into this:loadAll() async { await load(0, 'url1') .whenComplete(() async => await load(1, 'url2') .whenComplete(() async => await load(2, 'url3')));}
Leo D.
Updated on December 28, 2022Comments
-
Leo D. over 1 year
How can I let Flutter know to wait for one function (and therefore the future) to complete, until the next function is called? It seems like the load() function itself completes before the loadFeed() Future is finished, how can I fix that?
Here is my current code:
ValueNotifier<List> data = ValueNotifier([]); ValueNotifier<bool> loading = ValueNotifier(true); loadAll() async { await load(0, 'url1'); print("0 finished"); await load(1, 'url2'); print("1 finished"); await load(2, 'url3'); print("2 finished"); } load(int categoryIndex, String _url) async { loadFeed(_url).then((result) { if (null == result || result.toString().isEmpty) { print("error"); return; } data.value = [[],[],[],]; for (var i = 0; i < result.items.length; i++) { data.value[categoryIndex].add(result.items[i]); } data.notifyListeners(); }); } Future<RssFeed> loadFeed(String _url) async { loading.value = true; try { final client = http.Client(); final response = await client.get(Uri.parse(_url)); return RssFeed.parse(response.body); } catch (e) { print("error"); } finally { loading.value = false; } return null; }
-
jamesdlin about 3 yearsYou don't need to use
.whenComplete()
if you're already usingawait
.