on<E extends Event> method
void
on<E extends Event>(
- EventHandler<
E, ViewState< handler, {T> > - EventTransformer<
E> ? transformer,
inherited
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 CounterIncrementPressed extends CounterEvent {}
class CounterBloc extends Bloc<CounterEvent, int> {
CounterBloc() : super(0) {
on<CounterIncrementPressed>((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:
EventTransformer
to customize how events are processed.- package:bloc_concurrency for an opinionated set of event transformers.
Implementation
void on<E extends Event>(
EventHandler<E, State> handler, {
EventTransformer<E>? transformer,
}) {
// ignore: prefer_asserts_with_message
assert(() {
final handlerExists = _handlers.any((handler) => handler.type == E);
if (handlerExists) {
throw StateError(
'on<$E> was called multiple times. '
'There should only be a single event handler per event type.',
);
}
_handlers.add(_Handler(isType: (dynamic e) => e is E, type: E));
return true;
}());
final subscription = (transformer ?? _eventTransformer)(
_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,
);
Future<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);
rethrow;
} finally {
onDone();
}
}
handleEvent();
return controller.stream;
},
).listen(null);
_subscriptions.add(subscription);
}