felangel / bloc

A predictable state management library that helps implement the BLoC design pattern
https://bloclibrary.dev
MIT License
11.8k stars 3.39k forks source link

feat(flutter_bloc): add `RedirectingBlocListener` #3370

Closed purplenoodlesoop closed 2 years ago

purplenoodlesoop commented 2 years ago

Hi, folks!

Thanks for the updated documentation about bloc-to-bloc communication – turns out, I was doing it wrong most of the time :))

After refactoring a codebase that used the old way of communication, a pattern that was used throughout BlocListeners emerged.

A bloc-to-bloc communication in a configuration (Widgets) layer can be abstracted out through a new kind of BlocListener – a RedirectingBlocListener that would declaratively describe the relationship between states and events. Bellow is a naive implementation of such a listener:

typedef RedirectingBlocWidgetListener<S, E> = E? Function(
  BuildContext context,
  S state,
);

class RedirectingBlocListener<A extends StateStreamable<S>, S,
    B extends BlocEventSink<E>, E> extends BlocListener<A, S> {
  RedirectingBlocListener({
    Key? key,
    required RedirectingBlocWidgetListener<S, E> listener,
    A? bloc,
    BlocListenerCondition<S>? listenWhen,
    Widget? child,
  }) : super(
          key: key,
          child: child,
          listener: (context, state) {
            final event = listener(context, state);
            if (event != null) context.read<B>().add(event);
          },
          bloc: bloc,
          listenWhen: listenWhen,
        );
}

It would help to reduce repetitive code, enforce decomposition and modularity, and semantically state, what that listener does, exactly. I see it as a good candidate that could be added to the flutter_bloc package.

(I'm not making any statements on the naming though, it is just an example and there sure can be better names.)

Excited to hear everyone's opinions on that. Thanks!

narcodico commented 2 years ago

I personally feel that with good architecture you rarely end up in a situation where you need to add events from bloc to bloc, so such a widget is not essential.

felangel commented 2 years ago

I've thought about this a bit more and feel as though this isn't really a "core" component. In most cases, when such a scenario presents itself I prefer to move the shared state down to the repository layer so that multiple blocs can subscribe to the same source of data rather than keeping them in sync via the widget layer.