Bloc 8版本中transformEvents方法将被移除,改用onEvent方法后如何实现事件防抖?
Awesome question! With Bloc 8 deprecating transformEvents, switching to Bloc's newer APIs for debouncing is totally straightforward—let's break down the two best approaches depending on your needs:
Option 1: Debounce Specific Events (Recommended)
If you only need debouncing for certain events (the most common use case), Bloc 8+ lets you add a transformer directly when registering your event handler with on<Event>. This is cleaner and more flexible than the old global transformEvents approach.
Here's how to implement it:
class PriceProposalBloc extends Bloc<PriceProposalEvent, PriceProposalState> { PriceProposalBloc() : super(PriceProposalInitial()) { // Apply debounce to a specific event (e.g., PriceUpdateEvent) on<PriceUpdateEvent>( (event, emit) async { // Your event logic goes here—fetch data, update state, etc. emit(PriceProposalLoading()); final updatedPrice = await fetchPriceData(event.inputParams); emit(PriceProposalLoaded(price: updatedPrice)); }, // Add the debounce transformer directly to this event transformer: (events, mapper) => events.debounceTime(const Duration(milliseconds: 200)).asyncMap(mapper), ); // Other events can be registered normally without debouncing on<ResetPriceEvent>( (event, emit) => emit(PriceProposalInitial()), ); } }
Option 2: Global Debounce for All Events
If you need to apply debouncing to every event (matching your old transformEvents behavior), you can create an internal stream controller to handle debouncing globally, then override onEvent to route all events through this stream:
import 'dart:async'; import 'package:bloc/bloc.dart'; import 'package:rxdart/rxdart.dart'; class PriceProposalBloc extends Bloc<PriceProposalEvent, PriceProposalState> { final _debouncedEventStream = StreamController<PriceProposalEvent>(); PriceProposalBloc() : super(PriceProposalInitial()) { // Listen to the debounced stream and pass events to Bloc's internal handler _debouncedEventStream.stream .debounceTime(const Duration(milliseconds: 200)) .listen((event) => super.onEvent(event)); } @override void onEvent(PriceProposalEvent event) { // Route all incoming events to our debounced stream instead of processing immediately _debouncedEventStream.add(event); // Uncomment this line if you want to keep Bloc's default event logging (useful for dev mode) // super.onEvent(event); } @override Future<void> close() { // Don't forget to close the stream controller to avoid memory leaks! _debouncedEventStream.close(); return super.close(); } // Register your event handlers as usual @override void on<Event extends PriceProposalEvent>(EventHandler<Event, PriceProposalState> handler) { super.on(handler); } }
Quick Notes:
- Option 1 is preferred because it gives you granular control over which events get debounced—no need to apply a one-size-fits-all rule.
- For Option 2, always remember to close the stream controller in the
closemethod to prevent memory leaks.
内容的提问来源于stack exchange,提问作者Hamed Rezaee

