Skip to content

Instantly share code, notes, and snippets.

@przbadu
Created March 24, 2022 02:21
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save przbadu/1e2abb96dbe2fb1bb71433f30396e24d to your computer and use it in GitHub Desktop.
Save przbadu/1e2abb96dbe2fb1bb71433f30396e24d to your computer and use it in GitHub Desktop.
Bloc, cubit and stream short intro

bloc_example

In this project we will learn what is Bloc and how to use it by practical examples provided in

https://bloclibrary.dev/#/coreconcepts

Stream:

Read more on https://dart.dev/tutorials/language/streams

  • Streams provide an asynchronous sequence of data
  • Data sequences include user-generated events and data read from files.
  • You can process a stream using either await for or listen() from the Stream API
  • Streams provide a way to respond to errors.
  • There are two kinds of streams: single subscription or broadcast

In short: A stream is a sequence of asynchronous events. It is like an asynchronous Iterable—where, instead of getting the next event when you ask for it, the stream tells you that there is an event when it is ready.

Streams can be created in many ways, which is a topic for another article, but they can all be used in the same way: the asynchronous for loop (commonly just called await for) iterates over the events of a stream like the for loop iterates over an Iterable. For example:

Example

Future<int> sumStream(Stream<int> stream) async {
  int sum = 0;
  // await for stream and perform sum operation on stream value
  await for (int value in stream) {
    sum += value;
    // if you want to see the stream value.
    print("sum: $sum, stream: $value");
  }
  return sum;
}

// async* allow us to use yield keyword and return `Stream` of data.
Stream<int> countStream(int max) async* {
  for (int i = 0; i < max; i++) {
    // yield push value of i through `stream`
    yield i;
  }
}

void main() async {
  /// Initialize a stream of integers 0-9
  Stream<int> stream = countStream(10);
  /// Compute the sum of the stream of integers
  int sum = await sumStream(stream);
  /// Print the sum
  print(sum); //
}

Cubit

  • A cubit is a class which extends BlocBase and can be extended to manage any type of state.

fig: cubit

  • A cubit can expose functions which can be invoke to trigger state changes.

example

/// define cubit and specify type of the state
/// in this case it is int. for complex states,
/// use Class e.g: User, Wallet, Category, Transaction, etc
class CounterCubit extends Cubit<int> {
  /// initial state is 0
  CounterCubit(): super(0);

  /// Or we can also accept external value
  // CounterCubit(int initialState): super(initialState);

  /// external state value can be set like this:
  // final cubitA = CounterCubit(0);
  // final cubitB = CounterCubit(10);
}
  • Each cubit has the ability to o/p a new state via emit.
class CounterCubit extends Cubit<int> {
  CounterCubit() : super(0);

  void increment() => emit(state + 1);
}

void main() {
  final cubit = CounterCubit();
  print(cubit.state) // 0 (initial state)
  cubit.increment();
  print(cubit.state); // 1 (incremented state)
  cubit.close();
}

Cubit and Stream usage

  • Cubit exposes a Stream which allow us to receive real-time state updates:
Future<void> main() async {
  final cubit = CounterCubit();
  final subscription = cubit.stream.listen(print); // 1
  cubit.increment();
  await Future.delayed(Duration.zero);
  await subscription.cancel();
  await cubit.close();
}

In the above snippet, we are subscribing to the CounterCubit and calling print on each state change. We are then invoking the increment function which will emit a new state. Lastly, we are calling cancel on the subscription when we no longer want to receive updates and closing the cubit.

Observing a Cubit

Whan a Cubit emits a new state, a Change occurs. We can observe all changes for a given Cubit by overriding onChange.

class CounterCubit extends Cubit<int> {
  CounterCubit() : super(0);

  void increment() => emit(state + 1);

  // Observing a cubit
  @override
  void onChange(Change<int> change) {
    super.onChange(change);
    print(change);
  }

  // Error Handling
  @override
  void onError(Object error, StackTrace stackTrace) {
    print('$error, $stackTrace');
    super.onError(error, stackTrace);
  }

  // we can then interact with the `Cubit` and observe all changes output to the console.
  void main() {
    CounterCubit()
      ..increment()
      ..close();
  }
}

// example output
// >  Change { currentState: 0, nextState: 1 }

References

https://bloclibrary.dev/#/coreconcepts https://dart.dev/tutorials/language/streams

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment