1

In my program, I have two different Blocs bloc1 and bloc2. I use MultiBlocProvider and add those two blocs. now I want to use BlocListener and BlocBuilder both inside the MultiBlocProvider. For bloc1 I want to BlocBuilderand for bloc2 I want to BlocListener. How can I do that?

Scaffold(
      body: MultiBlocProvider(
        providers: [
          BlocProvider<GenerateFieldsBloc>(
            create: (_) => bloc1,
          ),
          BlocProvider<SubmitFieldBloc>(
            create: (_) => bloc2,
          ),
        ],
        child:() //here how can I use both BlocListener and BlocBuilder ???
     ),
);
Akila Ishan
  • 147
  • 2
  • 12

3 Answers3

4

You could nest them as follows:

BlocListener<SubmitFieldBloc, SubmitFieldState>(
  listener: (context, state) {
    // listen to SubmitFieldBloc
  },
  child: BlocBuilder<GenerateFieldsBloc, GenerateFieldsState>(
    builder: (context, state) {
       // build with GenerateFieldsBloc 
    }
  ),
)
Stefan Galler
  • 781
  • 4
  • 12
  • I think using a `BlocConsumer` can reduce the boilerplate code since it combines both `BlocListener` and `BlocBuilder` in one widget :) – CoderUni Sep 19 '22 at 16:54
1

If you wrap the child with a builder widget you can use these providers. But you make sure to use the builder's context when reading providers.


Scaffold(
      body: MultiBlocProvider(
          providers: [
            BlocProvider<GenerateFieldsBloc>(
              create: (_) => bloc1,
            ),
            BlocProvider<SubmitFieldBloc>(
              create: (_) => bloc2,
            ),
          ],
        child: Builder(
          builder: (context) {
            return BlocListener<GenerateFieldsBloc, GenerateFieldsState>(
            listener: (context, state) {
              // TODO: implement listener
            },
            child: BlocBuilder<SubmitFieldBloc, SubmitFieldState>(
              builder: (context, state) {
                return Text('asdasd');
              },
            ),
          );
          }
        ),
      ),
    );

Salih Can
  • 1,562
  • 1
  • 9
  • 18
1

What you want is BlocConsumer which is a combo of BlocBuilder and BlocListener. This article gives a good description of the differences between the three. Here is the code snippet from that article for BlocConsumer:

BlocConsumer<OrdersBloc, OrdersState>(
  listenWhen: (context, state) {
    return state is OrdersState.OrderCompleted ||
        state is OrdersState.OrderRefunded;
  },
  listener: (context, state) {
    if (state is OrdersState.OrdersCompleted) {
      // Navigate to next screen
      Navigator.of(context).pushNamed('OrderCompletedScreen');
    } else if (state is OrdersState.OrderRefunded) {
      // Report to analytics
      Analytics.reportRefunded(state.orderId);
    }
  },
  buildWhen: (context, state) {
    return state is OrdersState.OrderCompleted ||
        state is OrdersState.OrderInProgress ||
        state is OrdersState.OrderRequested;
  },
  builder: (context, state) {
    if (state is OrdersState.OrderCompleted) {
      return Container(child: Text('Order Served!'));
    } else if (OrdersState.OrderInProgress) {
      return Container(child: Text('In Progress'));
    } else {
      return Container(child: Text('No State'));
    }
  },
);
ubiquibacon
  • 10,451
  • 28
  • 109
  • 179