MultiBlocProvider not instantiating all bloc providers - how to properly work with MultiBlocProvider?
Asked Answered
D

2

7

I am using flutter_bloc and leveraging the MultiBlocProvider widget. Things were working fine, and then at some point, my MultiBlocProvider just refused to instantiate any new Blocs I created and added to it. I am pretty new to flutter_bloc so any pointers would help.

From my sample below, I had ItemListsBloc and CartBloc before this problem, and those continue to get instantiated correctly. The problem here is the LoadFaves bloc, and any other new blocs i have tried to add.

Any help would be appreciated.

Here is my MultiBlocProvider:

 @override
  Widget build(BuildContext context) {
    return MultiBlocProvider(
      providers: [
        BlocProvider(
          create: (context) => ItemListsBloc()..add(LoadItemLists()),
        ),
        BlocProvider(
          create: (context) =>
              FaveBloc()..add(LoadFaves('3pujK2EPXFaIPue3F42kSMTLgDV2')),
        ),
        BlocProvider(
          create: (context) => CartBloc()..add(CartInitialize()),
        ),
      ],
      child: BlocBuilder<ItemListsBloc, ItemListsState>(
        builder: (context, state) {
          if (state is ItemListsLoaded) {
            return Column(children: [
              Categories(items: state.items.values.toList()),
              SizedBox(
                height: 10.0,
              ),
              Expanded(
                child: ListView(
                  shrinkWrap: true,
                  children: _buildItemLists(state.itemLists, state.items),
                ),
              )
            ]);
          }

          return Container();
        },
      ),
    );
  }

And here are the "problematic" blocs:

class FaveBloc extends Bloc<FaveEvent, FaveState> {
  final FavesRepository _favesRepository = FavesRepository.instance;
  StreamSubscription _favesSubscription;

  @override
  FaveState get initialState => FaveInitial();

  @override
  Stream<FaveState> mapEventToState(
    FaveEvent event,
  ) async* {
    if (event is LoadFaves) {
      yield* _mapLoadFavesToState(event);
    } else if (event is UpdateFaves) {
      yield* _mapUpdateFavesToState(event);
    }
  }

  Stream<FaveState> _mapLoadFavesToState(LoadFaves event) async* {
    _favesSubscription?.cancel();
    _favesSubscription = _favesRepository.faves(event.userId).listen(
          (faves) => add(UpdateFaves(faves)),
        );
  }

  Stream<FaveState> _mapUpdateFavesToState(UpdateFaves event) async* {
    yield FavesUpdated(event.faves);
  }
}

and

class OrderBloc extends Bloc<OrderEvent, OrderState> {
  final OrderRepository _orderRepository = OrderRepository.instance;
  StreamSubscription _ordersSubscription;
  StreamSubscription _currOrderSubsction;

  @override
  OrderState get initialState => OrdersUnitialized();

  @override
  Stream<OrderState> mapEventToState(
    OrderEvent event,
  ) async* {
    if (event is OrderCreated) {
      yield* _mapOrderCreatedToState(event);
    } else if (event is OrdersUpdated) {
      yield* _mapOrderUpdateToState(event);
    } else if (event is OrderLoadRequest) {
      yield* _mapLoadReqToState();
    }
  }

  Stream<OrderState> _mapLoadReqToState() async* {
    _ordersSubscription?.cancel();
    _ordersSubscription = _orderRepository.orders().listen(
          (orders) => add(OrdersUpdated(orders)),
        );
  }

  Stream<OrderState> _mapOrderCreatedToState(OrderCreated event) async* {
    var orderId = await _orderRepository.createNewOrder(event.order);

    var state = this.state as OrdersLoadSuccess;

    yield state.copyWith(currentOrderId: orderId);
  }

  Stream<OrderState> _mapOrderUpdateToState(OrdersUpdated event) async* {
    yield OrdersLoadSuccess(orders: event.orders);
  }

  @override
  Future<void> close() {
    _ordersSubscription?.cancel();
    _currOrderSubsction?.cancel();
    return super.close();
  }
}

Thank you very much in advance

Duple answered 17/6, 2020 at 4:2 Comment(0)
D
14

By default, blocs are created lazily by BlocProvider which means create will not be called until the bloc is looked up via BlocProvider.of(context). You can set lazy to false on BlocProvider to force the blocs to be created immediately.

BlocProvider(
  lazy: false,
  create: (_) => MyBloc(),
  child: MyChild(),
)

From Felix A.

Duple answered 17/6, 2020 at 5:1 Comment(0)
A
1

set lazy parameter to false

BlocProvider(
  lazy: false,
  create: (BuildContext context) => BlocA(),
  child: ChildA(),
);

According to docs:

By default, Create is called only when the instance is accessed. To override this behavior, set lazy to false.

Allanson answered 15/12, 2022 at 3:35 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.