Streams vs Futures in Flutter

Streams vs Futures in Flutter

Introduction

In today's this vs that version of Flutter, we will see the difference between Streams and Futures. Streams and Futures are widely used when we are dealing with async functions and data. Let's see what a stream is and what a future is after we will understand the differences between them

Streams

A stream is like a river or a pipeline carrying data objects, one at a time. A program can connect its input to one stream and its output to another stream, thus connecting two programs. Streams are the natural way of handling asynchronous events.

An example of when you might use streams is when receiving data from a socket. If you are downloading data from the internet, you don’t want the thread to block forever. You would open the socket, connect, and then listen. When data arrives, call a function that saves the data to disk. Because this may take several seconds or longer, you make an asynchronous call: write().

This is how you create a function that returns a stream in Flutter

Stream<int> countStream() async* {
 for (int i = 1; i <= 100; i++) {
   await Future.delayed(Duration(seconds:1));
   yield i;
 }
}

Now suppose I want to listen to this stream and make the changes appear on my screen. How would I do that? The answer is to use StreamBuilder.

StreamBuilder needs a stream and a builder function that will return the widget to be rendered. Here is the code for the same.

StreamBuilder(
  // listen to the stream provided by getValues function
 stream: getValues(),
 builder: (context,snapshot){
 return Center(child: Text(snapshot.data.toString()));  
 }
),

When you run the above code, on the screen you will see a text whose value will change every second by 1. Copy Paste the code and try running it on the emulator to see what is happening. Drake 06032022192928 (1).jpg

Futures

In an app, there are many features like fetching data from the internet, writing to a database, downloading a file, etc which takes a lot of time. If writing to the database was synchronous in nature then it would create a terrible UX for the user. The user will be stuck and will not be able to do anything in the app until the function is complete.

To overcome or avoid this, we use Futures. A Future class allows you to run work asynchronously to free up any other threads that should not be blocked. Sounds confusing?

Well, here is an example. If I want to fetch data from an API, I use an async-await function and return a future. I do that because I don't know how much time will it take to get data from the API. So, I don't want my user to be stuck there. I add a Future to my return value so that Flutter knows that this function must be executed in the background and let the rest of the app function properly.

Here is an example of a Future function

Future<int> fetchOrder() async{
  // Just wait for 2 seconds before returning the data. 
// We are returning the data not at this instance, but 2 seconds later when the function is called

  await Future.delayed(Duration(seconds: 2);
  int x = 3;
  return x;
}

The next question is, how do we show data coming from a Future function in our app? The answer is FutureBuilder. A FutureBuilder would need a future and builder function. The future will contain the future function in which we are awaiting and the builder will contain the widget that needs to be returned.

Now in the builder function, you can return different widgets depending upon different scenarios. For example, if my data has not loaded, I can show a loading screen or a shimmer effect screen. Once my data is loaded I will show my data.

Here is the code example to understand it in a better way.

child: FutureBuilder(
 future: fetchOrder(),
 builder: (context,snapshot){
 // when the future has been returned successfully
  if(snapshot.hasData())
 {
  return Center(child: Text(snapshot.data.toString()));
 }
 // when we are awaiting on the data to be recieved
if(snapshot.connectionState==ConnectionState.waiting)
 {
  return Center(child: Text("Please wait, we are fetching your data"));
 }
// the function is completed but we have nothing in our snapshot
return
 {
   return Center(child: Text("Sorry, no data found"));
 }
 },
)

Waiting kermit 06032022192757.jpg

Differences

Now that we have understood what Streams and Futures are in Flutter, let's have a look at the differences between them.

  1. A Future can't listen to a variable change. It's a one-time response. Stream is a continuous flow of data.

  2. Functions with streams use async* and yield whereas functions with futures use async-await

  3. FutureBuilder is used to listen to a future and StreamBuilder is used to listen to a stream

  4. FutureBuilder can be used for fetching data from a database/API or a file. StreamBuilder can be used for implementing a stopwatch or a real-time chat application.

Conclusion

With this, we conclude our article. We have learned about streams and futures. We also saw the differences between them and where can they be used. I hope you learned something new today and understood this concept of streams and futures.

You can appreciate and support my blogs via.

Let's connect on Twitter. Follow CSwithIyush for more amazing tutorials, tips/tricks on Flutter & DSA

Did you find this article valuable?

Support Ayush Pawar by becoming a sponsor. Any amount is appreciated!