Flutter - 在 children 上从 parent 访问 Bloc

Flutter - Access Bloc from parent on children

我有一个 parent 小部件,它有两个 Blocs:

...
@override
  Widget build(BuildContext context) {
    return MultiBlocProvider(
      providers: [
        BlocProvider<RestaurantBloc>(
          create: (BuildContext context) => RestaurantBloc(restaurantRepository: _restaurantRepository),
        ),
        BlocProvider<CartBloc>(
          create: (BuildContext context) => CartBloc(),
        ),
      ],
      child: RestaurantScreenWidget(),
    );
  }
...

parent 小部件的部分,其中 child 小部件是使用 CartBloc 和其他 Bloc:

生成的
...
BlocBuilder<RestaurantBloc, RestaurantState>(
  builder: (context, state) {
    if (state is RestaurantEmpty) {
      return Center(
        child: Text('Empty'),
      );
    }

    if (state is RestaurantLoaded) {
      final items = state.restaurantCategories;

      if (items.length >= 1) {
        return BlocBuilder<CartBloc, CartState>(
          builder: (context, cartState) {
            return Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: <CategoryList>[
                for (var item in items)
                  CategoryList(categoryName: item.name, categoryItems: item.items)
              ],
            ); 
          },
        );
      }

      return Center(
        child: Text('Empty restaurant'),
      );
    }

    return Center(
      child: Text(
        'Error'
      ),
    );
  }
),
...

然后生成各种 child 小部件。这些小部件需要访问 CartBloc 及其状态:

...
Padding(
  padding: EdgeInsets.only(top: 20),
  child: SizedBox(
    width: double.infinity,
    child: BlocBuilder<CartBloc, CartState>(
      builder: (context, cartState) {
        return RaisedButton(
          child: const Text('ADD TO BASKET'),
            color: Colors.blue,
             textColor: Colors.white,
             onPressed: () {
               BlocProvider.of<CartBloc>(context).add(
                 AddItemToCart(
                   itemCount: (state as ItemLoaded).amount,
                   itemPrice: args.itemPrice,
                   newItemId: args.itemId,
                   newItemRestrictions: (state as ItemLoaded).restrictions,
                   newItemName: args.itemName
                 )
               );
               Navigator.pop(context);
             },
           );
         } 
       ), 
     ),
   ),
   ...

但是这样做,它给出了错误:

但是,如果我将 MultiBlocProviderCartBloc 放在 child 小部件上,错误就会消失,但显然 parent 小部件不会共享child 小部件的状态。

如何处理需要在这两个小部件之间共享的状态? (生成 child 小部件推送到需要访问 CartBloc 及其状态的屏幕)。

这是一个很常见的错误。使用 BlocBuilder 小部件时,您必须将 bloc 实例提供给 'build.' 您可以通过在 BlocBuilder 中设置可选的“bloc”构造函数 属性 来做到这一点。

BlocBuilder<CameraBloc, CameraState>(
  bloc: CameraBloc(),
  builder: (context, state) {
    if (state is InitialCameraState) {
      return Container(
        child: AspectRatio(
          aspectRatio: controller.value.aspectRatio,
          child: CameraPreview(controller)));
    }

    return Container();
  },
);

在父小部件(带有 MultiBlocProvider 的小部件)中,用 Builder 包装 RestaurantScreenWidget。