State management with Stream

Tram Ho

Introducing Stream

Asynchronous programming is a common term in programming. With the Dart programming language, we are used to the Future class which provides a computation that is not completed immediately and will announce the result when ready, which only does it once. Instead Stream is an asynchronous stream of events and allows us to listen to these events as they are fired from the stream.

A stream is a sequence of asynchronous events.

Stream classification

  • There are 2 types of Stream
    • Single subscription streams
    • Broadcast streams

    The basic understanding is that Single subscription streams can only listen once. (If there is an event listening from somewhere else or a 2nd time or more, an error will be raised). Broadcast streams , on the other hand, can listen anywhere.

Methods

  • The power of Stream not only makes asynchronous programming easy, but it also has very powerful support methods such as filter, transform…
  • See more at https://dart.dev/tutorials/language/streams
  • Support library: extension for Rxdart . stream
  • Refer to https://reactivex.io/ to learn about Reactivex/Functional reactive programming to learn about mechanism, how it works, how to use (supports many languages)

There is a small question: So what is the difference between these 2 types of Stream?

Why use Stream

  • Stream is a core Dart library/api.
    • → Easy to create Plugins (Split repo)
    • → Master the technology
  • Stream matches Flutter’s *declarative” style. (*** compared to the Imperative way in Native) and the MVVM model.
  • Reduce dependency on 3rd party libraries.
    • → Avoid errors when changing version
    • → Reduce app size
  • Some libraries like block, getx have mechanism that depends on Stream.

Building interfaces using StreamBuilder

StreamBuilder listens for Stream changes and refreshes the interface.

To use StreamBuilder need to call

Meaning of Parameters:

T? initialData : default value, if not passed in, is it considered not to have received data from Stream Stream<T>? stream : pass Stream to listen for and be processed at the required builder function AsyncWidgetBuilder<T> builder: Interface builder is set here

When building the UI, pay attention to the snapshot component in the builder

  • Check ConnectionState to see connection status with Stream
  • snapshot.hasError and snapshot.error: Check for errors and get errors. (Use addError to fire the error event)
  • snapshot.hasData and snapshot.data: Check for data and get data. (Use add to shoot out data)

ConnectionStates

  • When not casting Stream to StreamBuilder (meaning Stream is null) → none
  • When passing Stream ( initialData can be null or not) and have not added events → waiting
  • When transmitting Stream and adding events → active
  • When casting Stream and close() → done

Interface handler example:

[Demo] Building a countdown application using Stream

Demo below does not handle error states </aside>

Basic features:

Start – Pause – Resume – Refresh

Getting Started UI

UI Once Started

Steps to take

Declarations and functions are written in State of StatefulWidget

  • Create StreamController to manage data flow

  • Create StreamSubscription to manage the countdown

Stream.periodic(**const** Duration(seconds: 1), (computationCount) => **_start** - computationCount) creates a Stream that returns a value periodically after 1 second.

** _timeStreamController**.add(event); add new time to Stream

  • Display data on the interface

  • Extension get time information from type int

  • In order giúp cho các công việc không thực hiện lại công việc nó đang thực hiện , call the functions through the streamController

[Demo] Create your own flutter_bloc in Cubit style with Stream

  • In order to increase data readability and divide the source code between the interface and the logic we need to separate the processing at the

Step 1: Create an abstract class to define the block’s basic variables and functions

**_streamCtrl** = StreamController.broadcast()..add(initValue); stream cannot receive this event because stream.listen is called after the constructor function runs.

You can initValue yourself in StreamBuilder or use the RxDart library that supports this function

</aside>

Step 2:

  • Create TimerCubit
  • Bring all declarations and functions into TimerCubit

Step 3: Create BlocProvider

  • Creating a BlocProvider to manage the block instance by context, if you don’t want to do it this way, you can create a global variable for your own management.
  • BlocProvider is used from InheritedWidget

Step 4: Declare

<aside> Full code → </aside>

Additional features available

  • Can custom _Content to BlocBuilder
  • Add features like buildWhen, listenner
  • MultiBlocProvider

Reference

https://dart.dev/tutorials/language/streams

https://medium.flutterdevs.com/exploring-streambuilder-in-flutter-5958381bca67

https://reactivex.io/

Share the news now

Source : Viblo