on<E extends Event> method

void on<E extends Event>(
  1. EventHandler<E, State> handler, {
  2. EventTransformer<E>? transformer,
})

Register event handler for an event of type E. There should only ever be one event handler per event type E.

abstract class CounterEvent {}
class Increment extends CounterEvent {}

class CounterBloc extends Bloc<CounterEvent, int> {
  CounterBloc() : super(0) {
    on<Increment>((event, emit) => emit(state + 1));
  }
}
  • A StateError will be thrown if there are multiple event handlers registered for the same type E.

By default, events will be processed concurrently.

See also:

Implementation

void on<E extends Event>(
  EventHandler<E, State> handler, {
  EventTransformer<E>? transformer,
}) {
  assert(() {
    final handlerExists = _handlerTypes.any((type) => type == E);
    if (handlerExists) {
      throw StateError(
        'on<$E> was called multiple times. '
        'There should only be a single event handler per event type.',
      );
    }
    _handlerTypes.add(E);
    return true;
  }());

  final _transformer = transformer ?? Bloc.transformer;
  final subscription = _transformer(
    _eventController.stream.where((event) => event is E).cast<E>(),
    (dynamic event) {
      void onEmit(State state) {
        if (isClosed) return;
        if (this.state == state && _emitted) return;
        onTransition(Transition(
          currentState: this.state,
          event: event as E,
          nextState: state,
        ));
        emit(state);
      }

      final emitter = _Emitter(onEmit);
      final controller = StreamController<E>.broadcast(
        sync: true,
        onCancel: emitter.cancel,
      );

      void handleEvent() async {
        void onDone() {
          emitter.complete();
          _emitters.remove(emitter);
          if (!controller.isClosed) controller.close();
        }

        try {
          _emitters.add(emitter);
          await handler(event as E, emitter);
        } catch (error, stackTrace) {
          onError(error, stackTrace);
        } finally {
          onDone();
        }
      }

      handleEvent();
      return controller.stream;
    },
  ).listen(null);
  _subscriptions.add(subscription);
}