Watcher

The Watcher state flow

Overview

A Watcher is a type of use case that streams data and continuously emits either a Left Event (error) or a Right Event (data) as long as the corresponding stream is active.

However, before a stream can start emitting events, it must first be started. If the stream fails to start, then a Left Value (error) will be emitted. If the stream starts successfully, then a Right Value (a VerboseStream containing the stream being listened to) will be emitted.

A Watcher can emit 7 possible class states, all of which inherit the WatcherState sealed class:

Watcher States
Description

WatcherInitial

The initial state or the state emitted when the use case has been reset.

StartWatching

The state emitted when the stream creation is in progress.

StartWatchSuccess

The state emitted when the stream creation succeeds.

StartWatchFailed

The state emitted when the stream creation fails.

WatchDataReceived

The state emitted when the stream emits a new data.

WatchErrorReceived

The state emitted when the stream emits an error.

WatchDone

The state emitted when the stream has been closed.

A Watcher also has the following properties that you can access:

Property
Description

value

The latest value returned when calling watch(). This may either be the leftValue if StartWatchFailed was recently emitted. Otherwise, this will be equal to the rightValue if StartWatchSuccess was more recent.

params

The latest params returned when calling watch(). This may either be the leftParams if StartWatchFailed was recently emitted. Otherwise, this will be equal to the rightParams if StartWatchSuccess was more recent.

leftValue

The last left value returned when a failed watch() was called.

leftParams

The last left params passed when a failed watch() was called.

rightValue

The last right value returned when a successful watch() was called. This references a VerboseStream containing the stream being listened to.

rightParams

The last right params passed when a successful watch() was called.

event

The latest event emitted by the Watcher. This can either be the leftEvent if WatchErrorReceived was recently emitted. Otherwise, this will be equal to the rightEvent if WatchDataReceived was more recent.

leftEvent

The last error event emitted by the Watcher.

rightEvent

The last data event emitted by the Watcher.

Creating a Watcher

Let's implement a Watcher use case called WatchFruitBasket that does the following:

  • Add fruits to the basket.

  • Emits all the fruits in the basket when new ones are added.

Begin by creating the following classes:

1. Create the Parameter class

This is the parameter class passed to the Watcher when creating and starting the stream.

2. Create the Left event class

This is the object returned when the Watcher emits a StartWatchFailed or a WatchErrorReceived state.

3. Create the Right event class

This is the object returned when the Watcher emits a WatchDataReceived state.

4. Create the Watcher

Pass the Parameter, Left and Right event classes to the Runner's generic arguments. Afterwards, implement the code logic in the onCall method:

Using a Watcher

1. Start the Watcher and emit an event

To start the Watcher stream, call the watch method:

The Watcher will emit the StartWatching state while the stream is being initiated. If it is successful, then a StartWatchSuccess state together with a Right Value will be emitted. Otherwise, a StartWatchFailed state will be emitted containing Left Value.

The Right Value holds a VerboseStream object which contains the stream being listened to.

Once the Watcher successfully starts watching, a WatchDataReceived state will be emitted containing the Right Event whenever the stream receives new data. On the other hand, if the stream receives an error, then a WatchErrorReceived will be emitted alongside a Left Event.

2. View the Watcher properties

The Watcher gives you access to the following properties:

3. Reset the Watcher

To clear the Watcher and reset it back to its initial state, call the reset method:

Flutter Example

Every use case is a descendent of BLoC cubit. Hence, we can manage its states via the flutter_bloc package.

Dart Example

To run the Dart demo:

  1. Clone to codenic_clean_arch repository.

  2. Navigate to the packages/codenic_bloc_use_case directory.

  3. Run the example code:

Last updated