on<E extends Event> method Null safety

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

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

  • A StateError will be thrown if there are multiple event handlers registered for the same type E.

  • A StateError will be thrown if there is a missing event handler for an event of type E when add is called.

By default, events will be processed concurrently.

See also:

Implementation

void on<E extends Event>(
  EventHandler<E, State> handler, {
  EventTransformer<Event>? 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 for each event.',
      );
    }
    _handlerTypes.add(E);
    return true;
  }());

  final _transformer = transformer ?? Bloc.transformer;
  final subscription = _transformer(
    _eventController.stream.where((event) => event is E),
    (dynamic event) async* {
      void onDone(_Emitter<State> emitter) {
        emitter.cancel();
        _emitters.remove(emitter);
      }

      void onEmit(State state, _Emitter<State> emitter) {
        if (isClosed) return;
        if (emitter.isCanceled) return;
        if (this.state == state && _emitted) return;
        onTransition(Transition(
          currentState: this.state,
          event: event as E,
          nextState: state,
        ));
        emit(state);
      }

      Stream<Event> handleEvent(_Emitter<State> emitter) async* {
        try {
          _emitters.add(emitter);
          await handler(event as E, emitter);
        } catch (error, stackTrace) {
          onError(error, stackTrace);
        } finally {
          onDone(emitter);
        }
      }

      late final _Emitter<State> emitter;
      emitter = _Emitter((state) => onEmit(state, emitter));
      yield* handleEvent(emitter).doOnCancel(() => onDone(emitter));
    },
  ).listen(null);
  _subscriptions.add(subscription);
}