Romeo Mihalcea
Romeo Mihalcea

Reputation: 10252

BlocConsumer accessing multiple providers

I have this app where my widget is wrapped with MultiBlocProvider where I send down 2 providers:

MultiBlocProvider(
    providers: [
      BlocProvider<AppCubit>(
        create: (BuildContext context) => AppCubit(),
      ),
      BlocProvider<ProfileCubit>(
        create: (BuildContext context) => ProfileCubit(),
      ),
    ],
    child: HomePage(),

On the HomePage widget I access the first one using a BlocConsumer but I don't know how to grab all of them. Do I need to keep nesting BlocConsumer into the builder section in order to access my providers? What is the recommended way of accessing the x number of providers I send down to my widgets?

class HomePage extends StatefulWidget {
  @override
  Widget build(BuildContext context) {
    return BlocConsumer<AppCubit, AppState>(
      ...
      builder: (context, state) {
        return Scaffold(
          backgroundColor: Theme.of(context).primaryColorLight,
          body: null,
        );
      },
      ...
    );
  }
}

Upvotes: 3

Views: 2823

Answers (1)

DJ2695
DJ2695

Reputation: 72

The MultiBlocProvider is adding your Blocs to the context down the BuildTree to the children of MultiBlocProvider, hence to the HomePage(). BlocConsumer is analog to using a BlocBuilder(for Rebuilding UI after State Change) and a BlocListener(for other reactions like navigation after State Change). You can assign your Blocs in the initState() like following:

 @override
  void initState() {
    super.initState();
    appCubit = BlocProvider.of<AppCubit>(context); 
    profileCubit = BlocProvider.of<ProfileCubit>(context);
    appCubit.add(SomeFetchEvent());
    profileCubit.add(SomeFetchEvent());
  }

NOTE: in the BlocConsumer/BlocBuilder you want to show UI regarding the current state. Therefore you must decide in during which State you want to nest the next BlocConsumer/BlocBuilder. For example:

BlocConsumer<AppCubit, AppState>(
      ...
      builder: (context, state) {
       if (state == *someState*){
        // Nest next Consumer
          BlocConsumer<ProfileCubit, AppState>(
          ...
          builder: (context, state) {
          if(state == *someState*){ return ...}
         },
         ...
        );
       }
      },
      ...
    );

You might see, that it is not really useful to do that. If you don't need to change your UI if a State changes in AppCubit it would be useful to consider putting it in a BlocListener and put Profile Cubit in a BlocConsumer/BlocBuilder. For example:

 @override
  Widget build(BuildContext context) {
     return Scaffold(
          backgroundColor: Theme.of(context).primaryColorLight,
          body: BlocListener<AppCubit, AppState>(
               listener: (context, state) {
               // do some stuff here, like Navigating, Changing Variable at specific 
               // state
               },
               child: BlocBuilder<ProfileCubit, ProfileState>(
                builder: (context, state){
                // Change your UI according to the current state
                if(state == *someState*){
                 return *someWidget*
                  }
                }
           )
       ); 
   }


You will find more details here: https://bloclibrary.dev/#/flutterbloccoreconcepts?id=multiblocprovider

Upvotes: 1

Related Questions