【问题标题】:Flutter - Access Bloc from parent on childrenFlutter - 从父级访问 Bloc 到子级
【发布时间】:2020-06-22 18:46:20
【问题描述】:

我有一个包含两个 Bloc 的父小部件:

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

使用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'
      ),
    );
  }
),
...

然后它会生成各种子小部件。这些小部件需要访问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 放在子小部件上,错误就会消失,但显然父小部件不共享子小部件的状态。

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

【问题讨论】:

    标签: flutter bloc flutter-bloc


    【解决方案1】:

    这是一个很常见的错误。使用 BlocBuilder 小部件时,您必须将 bloc 实例提供给它以“构建”。您可以通过在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();
      },
    );
    

    【讨论】:

    • 我认为这个答案并不完全可以。在问题中,据说父小部件正在使用 BlocProvider 来创建 CartBloc,因此,据我所知,子小部件应该能够获取它。执行此答案的指示将创建一个新的 bloc 实例,而不是使用相同的实例。对吗?
    【解决方案2】:

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

    【讨论】:

      猜你喜欢
      • 2014-07-13
      • 2021-11-05
      • 1970-01-01
      • 1970-01-01
      • 2018-12-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多