2

I have a MainBloc that resides inside a main route, this route has a bottom app bar with multiple sub-routes, I want the same BLoC to run on all five sub-routes so that when one of them changes the state of the block the others will see the effect.

I tried this SO question but its really far from what I'm looking for, also I tried following what the error advised me to, but didn't work, here is the message that I got:

This can happen if:
    1. The context you used comes from a widget above the BlocProvider.
    2. You used MultiBlocProvider and didn't explicity provide the BlocProvider types.

    Good: BlocProvider<MainBloc>(builder: (context) => MainBloc())
    Bad: BlocProvider(builder: (context) => MainBloc()).

Main route:

@override
  Widget build(BuildContext context) {
    return MultiBlocProvider(
      providers: [
        BlocProvider<MainBloc>(
          builder: (BuildContext context) => MainBloc(),
        ),
        BlocProvider<OtherBloc>(
          builder: (BuildContext context) => OtherBloc(),
        ),
      ],
      child: /..., //here I have the bottom app bar with 5 buttons to navigate between sub-routes
);

one of the sub-routes:

@override
  Widget build(BuildContext context) {
    final MainBloc bloc = BlocProvider.of<MainBloc>(context);
    return /...; //here I have the context of this sub-route.
}

from what I've seen from tutorials and articles this code should work, but I can't seem to find why not.

Basel Abuhadrous
  • 1,444
  • 1
  • 14
  • 30

2 Answers2

4

The problem is you cannot access InheritedWidgets across routes unless you provide the InheritedWidget above MaterialApp. I would recommend wrapping your new route in BlocProvider.value to provide the existing bloc to the new route like:

        Navigator.of(context).push(
          MaterialPageRoute<MyPage>(
            builder: (_) {
              return BlocProvider.value(
                value: BlocProvider.of<MyBloc>(context),
                child: MyPage(),
              );
            },
          ),
        );

You can find more detailed information about this in the bloc documentation

Felix Angelov
  • 369
  • 2
  • 6
1

As this child has the bottom app bar: child: /..., //here I have the bottom app bar then I assume that the MultiBlocProvider(..) is not wrapping the whole part of app which is using this Bloc, my suggestion here is to wrap the "MaterialApp" with "MultiBlocProvider".

return MultiBlocProvider(
   providers: [..],
   child: MaterialApp(..) // Set MaterialApp as the child of the MultiBlocProvider
  //..
)
Jehad Nasser
  • 3,227
  • 5
  • 27
  • 39