How to write async code in Flutter

You may have heard that Dart is single threaded. Coming from a Java/Android background, it can be confusing. How do you handle async code? What concept replaces Android’s AsyncTask and Java’s threads? And how do you implement a callback?

The concept is called Futures. A Future completes with either a value or an error. You use a try/catch statement to catch the error. To create a Future, you use a Completer.

This all sounds very abstract, so let’s dive into an example.

In this code tutorial, we will set up a screen with 2 separate widgets. Both widgets use the same data repository as their data source. The data repository needs to make an API call to initialise its data. While it does so, the widgets show they are waiting for the data. When the data is ready, the widgets display it.

We will use a public API for the data, for exchange rates of the USD and GBP against the Euro. The first widget will show the USD exchange rate, the second the GBP rate. Both rates are obtained in one single call to https://exchangeratesapi.io/api/latest.

Setting up the app

To follow the code tutorial, create a new app as follows.

If you’re unsure how to set up a Flutter app, check out Getting started with Flutter official tutorial.

Firstly, we create a Material app in main.dart, which will launch the HomePage widget.

 

Secondly, we create home_page.dart. It uses 2 widgets: Widget1 and Widget2.

 

Lastly, we create the 2 widgets, in widget1.dart and widget2.dart respectively.

 

Setting up the data repository

The data repository is a singleton, so both widgets use the same instance. Let’s create a new file data_repository.dart.

 

Now, we can add an init() method, that calls the API. It returns a Future and we use the async keyword; this allows us to use await when calling the API. Then, we parse the result, and store the data in _exchangeRates. If there is any kind of error, _exchangeRates is null.

The code above includes some simple JSON parsing. If this is unclear to you, check out my code tutorial How to parse JSON in Dart / Flutter.

We initialise the data repository from home_page.dart.

 

Using a Future instead of a callback

BUT… when is the data ready? How can the widgets know? Instead of using a callback to know when the data is ready, we use a Future to retrieve the data. Let’s implement a getExchangeRates() method in data_repository.dart.

If the data is ready, getExchangeRates() returns the data immediately. If not, a completer is added to a list, its future is returned, and when init() completes, all the completers in the list complete with _exchangeRates value, prompting their futures to complete.

 

 

Now, in the widgets, we can safely call this new method without blocking the execution thread. Let’s amend widget1.dart and widget2.dart as below. Notice the use of the Future.then() construct in initState(): this is because we can’t use Future initState() async as initState() is an overridden method.

 

What next?

Reading Asynchronous Programming: Futures on Dart’s website is well worth your time. In particular, don’t forget to handle errors! If you want the error to cascade to your UI, do not catch it until you need to handle it (eg show something different in the UI). If, however, you want to swallow errors, eg trying to read data from one place but then using a backup method if it fails, then do remember to use try/catch.

 

Author: Natalie Masse Hooper

Mobile app developer with 12 years experience. Started with the Android SDK in 2010 and switched to Flutter in 2017. Past apps range from start ups to large tech (Google) and non tech (British Airways) companies, in various sectors (transport, commercial operations, e-commerce).

One thought on “How to write async code in Flutter”

Leave a Reply

Your email address will not be published.