Wait for all async function to complete before in executing in Flutter

Viewed 7182

I am using Flutter for my app. I need to query a large number of information from Firebase Realtime Database (e.g 50 different data location), therefore I need to launch them asynchronously and wait for all of them to return before updating the UI to show user the information.

How can I achieve this in Flutter? Using async, await, I could only wait for 1 async function.

1 Answers

Please check out Future.wait method. With Future.wait() you can launch multiple requests and then wait for all of them to complete. I've also given example code below.

wait method

Future<List<T>> wait <T>(

    Iterable<Future<T>> futures,
    {bool eagerError: false,
    void cleanUp(
        T successValue
    )}

)

Waits for multiple futures to complete and collects their results.

Returns a future which will complete once all the provided futures have completed, either with their results, or with an error if any of the provided futures fail.

The value of the returned future will be a list of all the values that were produced in the order that the futures are provided by iterating futures.

If any future completes with an error, then the returned future completes with that error. If further futures also complete with errors, those errors are discarded.

If eagerError is true, the returned future completes with an error immediately on the first error from one of the futures. Otherwise all futures must complete before the returned future is completed (still with the first error; the remaining errors are silently dropped).

In the case of an error, cleanUp (if provided), is invoked on any non-null result of successful futures. This makes it possible to cleanUp resources that would otherwise be lost (since the returned future does not provide access to these values). The cleanUp function is unused if there is no error.

The call to cleanUp should not throw. If it does, the error will be an uncaught asynchronous error.

Please see example code below, the result from all the three futures is loaded in ListView simultaneously, since Future.wait waits for all Futures to complete before returning the result :

import 'package:flutter/material.dart';

void main(List<String> args) {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  Future<List<String>> futureWait() async {
    return Future.wait([
      Future.delayed(const Duration(seconds: 1), () => "First Future Done"),
      Future.delayed(const Duration(seconds: 2), () => "Second Future Done"),
      Future.delayed(const Duration(seconds: 3), () => "Third Future Done"),
    ]);
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: const Text("Flutter Demo App"),
        ),
        body: FutureBuilder<List<String>>(
          future: futureWait(),
          builder: (context, snapshot) {
            if (snapshot.hasData) {
              print(snapshot.data.length);
              return ListView.builder(
                itemCount: snapshot.data.length,
                itemBuilder: (context, index) => ListTile(
                  title: Text(snapshot.data[index]),
                ),
              );
            }
            return const Center(child: CircularProgressIndicator());
          },
        ),
      ),
    );
  }
}
Related