on<E extends Event> method
void
on<E extends Event>(
- EventHandler<
E, RoomState> handler, { - 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 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:
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,
}) {
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);
}