0PricingLogin
Flutter Mobile Development · Lesson

Stream Transformers and Event Debouncing in BLoC

Apply concurrency transformers to throttle, debounce, and sequence incoming events.

Why Event Concurrency Matters

In flutter_bloc, every call to add(event) pushes an event into an internal stream. By default each event handler runs concurrently as events arrive. For most events that is fine, but some sources fire far too often:

  • Search bars emit a TextChanged event on every keystroke.
  • Scroll listeners emit dozens of ScrolledToBottom events per second.
  • Buttons can be tapped rapidly, firing duplicate SubmitPressed events.

Firing a network request per keystroke wastes bandwidth and can show stale results. This lesson shows how to throttle, debounce, and sequence these events using stream transformers in BLoC.

The transformer Parameter

The modern on<Event> API accepts an optional transformer argument. A transformer is an EventTransformer<E> — a function that receives the incoming Stream<E> of events and a mapper, and returns a transformed stream.

By supplying a transformer you control how events of that type are processed: debounced, throttled, dropped, or run one-at-a-time. The signature is:

  • typedef EventTransformer<Event> = Stream<Event> Function(Stream<Event> events, EventMapper<Event> mapper);

You rarely write transformers by hand — the bloc_concurrency package provides the common ones.

// Registering a handler with a custom transformer
on<SearchTermChanged>(
  _onSearchTermChanged,
  transformer: (events, mapper) => events
      .debounceTime(const Duration(milliseconds: 300))
      .switchMap(mapper),
);

All lessons in this course

  1. Events, States, and the Cubit-vs-Bloc Decision
  2. Stream Transformers and Event Debouncing in BLoC
  3. Persisting State with HydratedBloc
  4. Testing BLoCs with bloc_test and Mocktail
← Back to Flutter Mobile Development