Bloc: How can I pass references for blocs to each other at creation?

Created on 12 Aug 2020  路  3Comments  路  Source: felangel/bloc

Hi, just wondering how to do something - I found some similar issues to this but couldn't find a solution that worked for me (maybe updates changed the functionality, I don't know)

Anyway, I have this situation:

return MultiBlocProvider(
      providers: [
        BlocProvider<AppBloc>(
          //bloc: appBloc,
          create: (_) => AppBloc()..add(AppStarted()),
        ),
        BlocProvider<GameBloc>(
          create: (_) => GameBloc(
              config: config,
              appBloc: BlocProvider.of<AppBloc>(context),
              boardBloc: BlocProvider.of<BoardBloc>(context),
              timerBloc: BlocProvider.of<TimerBloc>(context),
          )..add(GameCreated()),
        ),
        BlocProvider<HomeBloc>(
          create: (_) => HomeBloc(
              config: config,
              gameBloc: BlocProvider.of<GameBloc>(context),
          )..add(HomeStarted()),
        ),
        BlocProvider<BoardBloc>(
          create: (_) => BoardBloc(
              appBloc: BlocProvider.of<AppBloc>(context),
              gameBloc: BlocProvider.of<GameBloc>(context),
          ),
        ),
        BlocProvider<TimerBloc>(
          create: (_) => TimerBloc(),
        ),
      ],
      child: MaterialApp()
);

I actually found this solution from someone else who had the same problem (can't find the issue now but it was older than a year). However, it doesn't work and I get this error:
BlocProvider.of() called with a context that does not contain a Cubit of type GameBloc.
I take this to mean that Bloc B referencing Bloc A has to exist in a context below Bloc A.

So how do I achieve this? I saw some previous posts saying to do something like this:

AppBloc appBloc = AppBloc();
GameBloc gameBloc = GameBloc(appBloc: appBloc);
appBloc.gameBloc = gameBloc; // just for illustration
    return MultiBlocProvider(
      providers: [
        BlocProvider<AppBloc>(
          bloc: appBloc,
        ),
        BlocProvider<GameBloc>(
          bloc: gameBloc,
        ),
)

However, I think this is out of date because the BlocProvider constructor doesn't have a 'bloc' parameter for me and it doesn't in the documentation (as far as I can see) either.

Is there any smart solution to this?

question

All 3 comments

Hi @alexobviously 馃憢

You're getting that error because you're using current widget's context when trying to retrieve your providers thus it cannot find them, since your providers are declared within that very own context.

To fix this you should use the context given you by the create method explicitly. E.g.:

BlocProvider<HomeBloc>(
          create: (context) => HomeBloc(
              config: config,
              gameBloc: BlocProvider.of<GameBloc>(context),
          )..add(HomeStarted()),
        ),

Oh duh that's seems so obvious now you've said it! Thanks.

I'm still having a problem now with:

providers: [
        BlocProvider<AppBloc>(
          //bloc: appBloc,
          create: (ctx) => AppBloc()..add(AppStarted()),
        ),
        BlocProvider<GameBloc>(
          create: (ctx) => GameBloc(
              config: config,
              appBloc: BlocProvider.of<AppBloc>(ctx),
              boardBloc: BlocProvider.of<BoardBloc>(ctx),
              timerBloc: BlocProvider.of<TimerBloc>(ctx),
          )..add(GameCreated()),
        ),
        BlocProvider<HomeBloc>(
          create: (ctx) => HomeBloc(
              config: config,
              gameBloc: BlocProvider.of<GameBloc>(ctx),
          )..add(HomeStarted()),
        ),
        BlocProvider<BoardBloc>(
          create: (ctx) => BoardBloc(
              appBloc: BlocProvider.of<AppBloc>(ctx),
              gameBloc: BlocProvider.of<GameBloc>(ctx),
          ),
        ),
        BlocProvider<TimerBloc>(
          create: (ctx) => TimerBloc(),
        ),
      ],

Specifically I get an error (the same one) on this line:
boardBloc: BlocProvider.of<BoardBloc>(ctx),

So I guess this is a problem with the ordering of my blocs: if I put the BoardBloc before GameBloc this won't happen, but the BoardBloc also needs to reference the GameBloc so how do I go about that? Just set BlocA.blocB manually in the constructor of BlocB? That's a bit messy so I'd rather do it the proper way if there is one.

You can instantiate your problematic blocs in main and pass the reference directly.
You should maybe rethink how your blocs look like since there's too much interdependency between them.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

hivesey picture hivesey  路  3Comments

shawnchan2014 picture shawnchan2014  路  3Comments

nhwilly picture nhwilly  路  3Comments

MahdiPishguy picture MahdiPishguy  路  3Comments

Reidond picture Reidond  路  3Comments