-
-
Notifications
You must be signed in to change notification settings - Fork 3.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: add EventTransformer
for all incoming events
#3623
Comments
@maRci002 in your example class TestEventRefresh extends TestEvent {}
class TestEventLoadMoreItems extends TestEvent {} these are both derived events of the base The functionality you desire is to have a single event handler for the base event and handle all derived events inside of it. Like so: abstract class TestEvent {}
class TestEventRefresh extends TestEvent {}
class TestEventLoadMoreItems extends TestEvent {}
class TestBloc extends Bloc<TestEvent, List<int>> {
TestBloc.withItems(List<int> items) : super(items) {
on<TestEvent>( // subscribe to base event instead of derived events
_onTestEvent,
transformer: restartable(),
);
}
Future<void> _onTestEvent(
TestEvent event,
Emitter<List<int>> emit,
) async {
// handle derived events by narrowing them down individually and invoking their handlers
if (event is TestEventRefresh) _onTestEventRefresh(event, emit)
if (event is TestEventLoadMoreItems) _onTestEventLoadMoreItems(event, emit)
}
Future<void> _onTestEventRefresh(
TestEventRefresh event,
Emitter<List<int>> emit,
) async {
await Future.delayed(const Duration(seconds: 1));
emit(List.generate(10, (index) => index));
}
Future<void> _onTestEventLoadMoreItems(
TestEventLoadMoreItems event,
Emitter<List<int>> emit,
) async {
await Future.delayed(const Duration(seconds: 2));
final last = state.last + 1;
emit(state + List.generate(10, (index) => last + index));
}
} If either of the derived events are being handled and another derived event comes in, it will invoke the new handler and the pervious event handler is discarded and will no longer emit with |
@jacobtipp thanks for advice, I'm wondering if this is the way, I already thought about it. Unfortunatelly the output is the same this might be another issue ( #3349 #3586 ). I am advised to check import 'package:bloc/bloc.dart';
import 'package:bloc_concurrency/bloc_concurrency.dart';
abstract class TestEvent {}
class TestEventRefresh extends TestEvent {}
class TestEventLoadMoreItems extends TestEvent {}
class TestBloc extends Bloc<TestEvent, List<int>> {
TestBloc.withItems(List<int> items) : super(items) {
on<TestEvent>(
// subscribe to base event instead of derived events
_onTestEvent,
transformer: restartable(),
);
}
Future<void> _onTestEvent(
TestEvent event,
Emitter<List<int>> emit,
) async {
// handle derived events by narrowing them down individually and invoking their handlers
if (event is TestEventRefresh) _onTestEventRefresh(event, emit);
if (event is TestEventLoadMoreItems) _onTestEventLoadMoreItems(event, emit);
}
Future<void> _onTestEventRefresh(
TestEventRefresh event,
Emitter<List<int>> emit,
) async {
print('_onTestEventRefresh (1) active: ${!emit.isDone}');
await Future.delayed(const Duration(seconds: 1));
print('_onTestEventRefresh (2) active: ${!emit.isDone}');
emit(List.generate(10, (index) => index));
}
Future<void> _onTestEventLoadMoreItems(
TestEventLoadMoreItems event,
Emitter<List<int>> emit,
) async {
print('_onTestEventLoadMoreItems (1) active: ${!emit.isDone}');
await Future.delayed(const Duration(seconds: 2));
print('_onTestEventLoadMoreItems (2) active: ${!emit.isDone}');
final last = state.last + 1;
emit(state + List.generate(10, (index) => last + index));
}
}
Future<void> main() async {
final bloc = TestBloc.withItems(List.generate(10, (index) => index));
bloc.stream.listen(print);
// user reaches end of the ListView
bloc.add(TestEventLoadMoreItems());
// user scrolls up to trigger a refresh
await Future.delayed(const Duration(milliseconds: 200));
bloc.add(TestEventRefresh());
} Output:
|
@maRci002 I apologize, I forgot that the handler is async so you would need to await both derived event handlers change this: Future<void> _onTestEvent(
TestEvent event,
Emitter<List<int>> emit,
) async {
// handle derived events by narrowing them down individually and invoking their handlers
if (event is TestEventRefresh) _onTestEventRefresh(event, emit);
if (event is TestEventLoadMoreItems) _onTestEventLoadMoreItems(event, emit);
} to this: Future<void> _onTestEvent(
TestEvent event,
Emitter<List<int>> emit,
) async {
// handle derived events by narrowing them down individually and invoking their handlers
if (event is TestEventRefresh) await _onTestEventRefresh(event, emit); // must await here in order for it to resolve properly
if (event is TestEventLoadMoreItems) await _onTestEventLoadMoreItems(event, emit); // same as above ^
} let me know if this is your desired outcome |
@jacobtipp thank you very much your effort it works like a charm. Usually unawaited_futures is enabled on my projects so I would be forced to await derived event handlers. Output:
|
Description
Via
Bloc.on<E extends Event>(EventHandler<E, State> handler, {EventTransformer<E>? transformer})
anEventTransformer
's can be registered toBloc
. The registered transformer gets only the specificE
events.Problem is: multiple
EventHandler
cannot share the same transformer.For instance I've a
PaginatingBloc
which has twohandlers
withrestartable
transformer frombloc_concurrency
:_onTestEventLoadMoreItem
: load more items_onTestEventRefresh
: reloads the first 10 itemsif
_onTestEventLoadMoreItem
is called which takes 2 seconds then user also pulls for_onTestEventRefresh
which takes 1 second then the_onTestEventLoadMoreItem.emit
should be discarded.Output:
Desired Output:
The text was updated successfully, but these errors were encountered: