Flutter Streams and Stream Builder.
In this tutorial, I am going to discuss the stream concept of the Flutter (Dart). After referring to this, you can gain a better understanding of Streams and how to implement them in your future Flutter Projects.
What is a stream?
In simple, the stream is like a river that has two ends. Think you are at the top end of the river and your friend is at the other end of the river. From time to time you put paper boats in the river and on the other hand, your friend can collect boats, that you put into the river.
Your friend doesn’t know when the next boat arrives (Asynchronous). But he always looking for a boat(Listening). You can put boats anytime you want. (Sinking data)
In a similar manner, we can explain how the stream works in Flutter or Dart.
stream has two main concepts. Sink and Source.
- Sink — where the put data into the stream.
- Stream — Where we listen to the stream.
Where the streams are used?
Flutter user stream in various places.
- Listen to notifications.
- work with real-time chat servers.
- Build apps witch UI change continuously according to the data. (eg: Stock exchange application)
- BLoC design pattern, that uses in a flutter as a state management tool. also uses the stream concept.
How to Implement
In this section, you will learn how to create and listen to a Stream. I will show you how to build a simple Timer application using the stream concept in Flutter/Dart.
There are two main ways to implement Streams. we are going to use both methods to build our simple app.
- Using StreamController class.
- using the yield keyword.
Using StreamController class
This way is more customizable and has its own pros and cons. First, we create a simple stateful widget as home.dart
then we create an instance of the StreamController class and by using this controller we’ll declare a function to add data to the stream. Finally, we start the stream by calling increament function inside the initState method.
Please remember, even though we create a stream manually. in real-world scenarios. we can use provided streams.
StreamBuilder Widget
Now our stream is ready. all we have to do is listen to the stream and re-build the UI accordingly. For that purpose, flutter gives a Builder widget called StreamBuilder.
Streambuilder requires stream argument. so we provide our stream controller object for that. The next argument is builder, it requires a widget, that needs to be built. snapshot is a variable that includes data, coming from the stream. we use some if-else conditions to build UI widgets accordingly.
- snapshot.hasData — true, if snapshot has data.
- snapshot.hasError — true, when an error occured.
- snapshot.connectionState — show connection state like waiting.
Since the StreamBuilder way is very manual, we need to close the stream subscription manually before leaving it to the next screen. Otherwise, the Stream might run in the background of the application and caused to happen memory leaks in the application.So we call<StreamController object name>.close() method inside the dispose() method.
Congratulations, you successfully completed the first way of using Flutter Streams. As well you have learned StreamBuilder widgets also. Here is the full code.
Using yield keyword.
This way you don’t need to create StreamController. Use yield keyword instead.
we modified our previous increment function with yield keyword. By using yield keyword, you can put data into the stream. But remember to use async* instead of async.
since we don’t have a StreamController object, we put the increment method for the stream argument in the StreamBuilder widget.
This second way is much handier than our manual StreamController way. We don’t need to worry about closing the stream after using it. It’ll handle by the program itself.
But the second way is not much more customizable than the StreamController way.
However congratulations. You just completed the second part of the tutorial also.
Here is the full code.
Conclusion
So let me summarize what we have learned so far.
- We use Streams when we need to listen to a continuous but asynchronous data flow.
- Sink — end, put data to the stream.
- Stream — end, listen to the data.
- StreamController — by creating an instance of the class we can listen to the stream. But need to close the stream after using it.
- yield and async* — handier way to handle streams.
Github link for code: https://github.com/DulsaraNethmin/streams.git
Thank you for reading.❤️