Reactive Programming with Flutter: Understanding Streams and Futures in Dart and How to Use Them in Flutter

Tram Ho

In the modern programming world, handling asynchronous tasks is becoming more and more important. Google’s Dart programming language and Flutter framework provide two powerful tools for working with asynchronous programming: Future and Streams . In this article, we will learn about both, as well as how they are used in Flutter .

Future in Dart

Future is a way to do work that might take a long time to complete, like reading data from a drive or making an HTTP request, without blocking the main thread of execution.

Here is an example of how to use Future in Dart:

In the above example, fetchUserOrder returns a Future<String>. When the Future completes, the return value is processed in the then method’s callback function.

Streams in Dart

Streams are like Futures, but instead of just returning a value, they can broadcast multiple value events over time. Streams are a good way to work with data asynchronously if you need to handle a lot of events or values.

Here is an example of how to use Streams:

In this example, countStream creates a Stream that plays numbers from 1 to to every second. We then listen to this Stream and print each value as it appears.

Using Futures and Streams in Flutter

In Flutter, both Future and Streams play an important role in building reactive application. For example, you can use Future to load data from an API and update the interface when the data is ready.

In the Future example, we are creating a Future that returns the string “Iced Coffee” after 3 seconds. FutureBuilder then listens to this Future and updates the interface when the data is ready.

Another aspect of reactive programming in Flutter is using StreamBuilder to listen for events from a Stream . Here is an example of how to use StreamBuilder :

For the Stream example, we create a Stream that broadcasts numbers from 1 to 5 every second. StreamBuilder listens to this Stream and updates the interface with each new number.

A few notes for programmers when using Streams and Future in Flutter

There are some important points that Flutter programmers need to remember when using Future and Streams:

1. Handling Future and Stream states

When using FutureBuilder or StreamBuilder , you need to handle all possible states of Future or Stream. This includes handling of wait states, completion states, and error states.

2. Make sure Future and Stream are not leaked

Future and Stream if not handled properly can lead to performance and memory problems. Make sure you always cancel Stream subscriptions when you no longer need them. For example, you can do this in the dispose method of StatefulWidget .

Here is a simulation example of StreamBuilder . StreamBuilder automatically cancels subscriptions when the widget is dismissed, so there’s no need to worry about manual cancellation:

In this example, StreamBuilder listens to a Stream that plays numbers from 0 every second and updates the interface with each new number.

3. Consider using state management libraries

There are many state management libraries in Flutter (like Provider, Riverpod, Bloc, etc.) that can help you manage and handle Futures and Streams more efficiently.

Example of using Provider to manage a simple value:

Here, we are using the ChangeNotifierProvider to provide a ValueNotifier<int>, a simple ChangeNotifier type, to the entire application. When the FloatingActionButton is clicked, the value in the ValueNotifier<int> will increase, and the Text widget will automatically update to show this new value.

4. Understanding parallel and sequential running

Future in Dart will run sequentially on one thread by default. However, with Future.wait , you can run multiple Futures in parallel. With Streams, you can use methods like Stream.map , Stream.where , Stream.expand , etc. to process and transform data dynamically.

Here is an example of running sequentially and in parallel with Future in Dart:

Sequential run:

In this example, ‘Future 2’ will wait for ‘Future 1’ to complete before starting, so they are executed sequentially.

Running parallel:

In this example, ‘Future 1’ and ‘Future 2’ are started at the same time and run in parallel. Future.wait waits for all Futures to complete before continuing.

Conclude

Future and Streams are two powerful tools in the Dart programming language for handling asynchronous tasks. Flutter leverages them through FutureBuilder and StreamBuilder to create powerful and flexible reactive applications. Hopefully after this article, you have a better understanding of how to use Future and Streams in Dart and Flutter.

Share the news now

Source : Viblo