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);
},
);
}
),
),
),
...
但是这样做,它给出了错误:
但是,如果我将 MultiBlocProvider
和 CartBloc
放在 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。
我有一个 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);
},
);
}
),
),
),
...
但是这样做,它给出了错误:
但是,如果我将 MultiBlocProvider
和 CartBloc
放在 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。