Flutter 中的 BlocProvider 错误及其修复方法
BlocProvider bug in Flutter and how to fix it
所以我在 BlocProvider 方面遇到了一些问题。这是我遇到的问题:
编辑:在主页上添加了 DrinkBloc 并更改了片段:
完整代码
@override
Widget build(BuildContext context) {
print("Building entire food list scaffold");
return Scaffold(
appBar: AppBar(title: Text("FoodList")),
//THE BLOCPROVIDER
body: BlocProvider(
//the issue might be that it is DrinkBloc(), but I have 2 separate tables, one after another
create: (BuildContext context) => DrinkBloc(),
child: Column(children: [
Row(
children: [
Text('Drinks'),
Divider(),
IconButton(
icon: Icon(Icons.add),
onPressed: () => Navigator.push(
context,
MaterialPageRoute(
builder: (BuildContext context) => DrinkForm())))
],
),
Expanded(
child: Container(
child: BlocConsumer<DrinkBloc, List<Drink>>(
builder: (context, drinkList) {
return ListView.separated(
itemBuilder: (BuildContext context, int index) {
print("drinkList: $drinkList");
Drink drink = drinkList[index];
return ListTile(
title: Text("${drink.name}",
style: TextStyle(fontSize: 30)),
onTap: () => showDrinkDialog(context, drink, index));
},
itemCount: drinkList.length,
separatorBuilder: (BuildContext context, int index) =>
Divider(color: Colors.black),
);
},
listener: (BuildContext context, drinkList) {},
),
),
),
Row(
children: [
Text('Foods'),
Divider(),
IconButton(
icon: Icon(Icons.add),
onPressed: () => Navigator.push(
context,
MaterialPageRoute(
builder: (BuildContext context) => FoodForm())))
],
),
Expanded(
child: Container(
child: BlocConsumer<FoodBloc, List<Food>>(
builder: (context, foodList) {
return ListView.separated(
itemBuilder: (BuildContext context, int index) {
print("foodList: $foodList");
Food food = foodList[index];
return ListTile(
title:
Text(food.name, style: TextStyle(fontSize: 30)),
subtitle: Text(
"Calories: ${food.calories}\nVegan: ${food.isVegan}",
style: TextStyle(fontSize: 20),
),
onTap: () => showFoodDialog(context, food, index));
},
itemCount: foodList.length,
separatorBuilder: (BuildContext context, int index) =>
Divider(color: Colors.black),
);
},
listener: (BuildContext context, foodList) {},
),
),
),
]),
),
class DrinkBloc extends Bloc<DrinkEvent, List<Drink>> {
@override
List<Drink> get initialState => List<Drink>();
@override
Stream<List<Drink>> mapEventToState(DrinkEvent event) async* {
if (event is SetDrinks) {
yield event.drinkList;
} else if (event is AddDrink) {
List<Drink> newState = List.from(state);
if (event.newDrink != null) {
newState.add(event.newDrink);
}
yield newState;
} else if (event is DeleteDrink) {
List<Drink> newState = List.from(state);
newState.removeAt(event.drinkIndex);
yield newState;
} else if (event is UpdateDrink) {
List<Drink> newState = List.from(state);
newState[event.drinkIndex] = event.newDrink;
yield newState;
}
}
}
片段:
body: BlocProvider(
create: (BuildContext context) => DrinkBloc(),
child: Column(children: [
Row(
我现在遇到的错误基本上是当我点击按钮添加饮料时('Drinks' 旁边的按钮)
No ancestor could be found starting from the context that was passed to BlocProvider.of<DrinkBloc>().
The context used was: DrinkForm(state: _DrinkFormState#5d9c5)
BlocProvider.of() called with a context that does not contain a Bloc of type DrinkBloc.
现在看起来如何(底部有效,但上部饮料无效,可能是因为我将整个东西都包裹在 DrinkBloc 中,不知道如何更改它
)
main.dart
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return BlocProvider<FoodBloc>(
create: (context) => FoodBloc(),
child: MaterialApp(
title: 'Sqflite Tutorial',
theme: ThemeData(
primarySwatch: Colors.deepPurple,
),
home: FoodList(),
),
);
}
}
您没有providing/injecting DrinkBloc
进入小部件树。
因此,当您尝试使用 BlocConsumer 访问 DrinkBloc
bloc 时,它会尝试查找该 bloc 的祖先。因为它丢失了,它会抛出那个特定的错误 BlocProvider.of() called with a context that does not contain a Bloc of type DrinkBloc.
对于 providing/injecting Drinkbloc
你可以使用 BlocProvider
如下:
BlocProvider(
create: (BuildContext context) => BlocA(),
child: ChildA(),
);
在任何地方调用它作为 BlocConsumer 的祖先。
例如:
Scaffold(
appBar: AppBar(title: Text("FoodList")),
body: BlocProvider(
create: (BuildContext context) => DrinkBloc(),
child: Column(children: [
...
],
);
为了让 BlocConsumer 在上下文中工作,它应该知道它使用的 bloc,因此,called with a context that does not contain a Bloc of type DrinkBloc.
在 flutter_bloc 文档中,您必须像这样定义提供程序
BlocProvider(
create: (BuildContext context) => DrinkBloc(),
child: Widget("this widget's context contains DrinkBloc"),
);
因此,只需将它放在小部件树中您想要放置的位置的更高位置,并将 BlocConsumer 放在其中的任何位置。
所以我在 BlocProvider 方面遇到了一些问题。这是我遇到的问题:
编辑:在主页上添加了 DrinkBloc 并更改了片段:
完整代码
@override
Widget build(BuildContext context) {
print("Building entire food list scaffold");
return Scaffold(
appBar: AppBar(title: Text("FoodList")),
//THE BLOCPROVIDER
body: BlocProvider(
//the issue might be that it is DrinkBloc(), but I have 2 separate tables, one after another
create: (BuildContext context) => DrinkBloc(),
child: Column(children: [
Row(
children: [
Text('Drinks'),
Divider(),
IconButton(
icon: Icon(Icons.add),
onPressed: () => Navigator.push(
context,
MaterialPageRoute(
builder: (BuildContext context) => DrinkForm())))
],
),
Expanded(
child: Container(
child: BlocConsumer<DrinkBloc, List<Drink>>(
builder: (context, drinkList) {
return ListView.separated(
itemBuilder: (BuildContext context, int index) {
print("drinkList: $drinkList");
Drink drink = drinkList[index];
return ListTile(
title: Text("${drink.name}",
style: TextStyle(fontSize: 30)),
onTap: () => showDrinkDialog(context, drink, index));
},
itemCount: drinkList.length,
separatorBuilder: (BuildContext context, int index) =>
Divider(color: Colors.black),
);
},
listener: (BuildContext context, drinkList) {},
),
),
),
Row(
children: [
Text('Foods'),
Divider(),
IconButton(
icon: Icon(Icons.add),
onPressed: () => Navigator.push(
context,
MaterialPageRoute(
builder: (BuildContext context) => FoodForm())))
],
),
Expanded(
child: Container(
child: BlocConsumer<FoodBloc, List<Food>>(
builder: (context, foodList) {
return ListView.separated(
itemBuilder: (BuildContext context, int index) {
print("foodList: $foodList");
Food food = foodList[index];
return ListTile(
title:
Text(food.name, style: TextStyle(fontSize: 30)),
subtitle: Text(
"Calories: ${food.calories}\nVegan: ${food.isVegan}",
style: TextStyle(fontSize: 20),
),
onTap: () => showFoodDialog(context, food, index));
},
itemCount: foodList.length,
separatorBuilder: (BuildContext context, int index) =>
Divider(color: Colors.black),
);
},
listener: (BuildContext context, foodList) {},
),
),
),
]),
),
class DrinkBloc extends Bloc<DrinkEvent, List<Drink>> {
@override
List<Drink> get initialState => List<Drink>();
@override
Stream<List<Drink>> mapEventToState(DrinkEvent event) async* {
if (event is SetDrinks) {
yield event.drinkList;
} else if (event is AddDrink) {
List<Drink> newState = List.from(state);
if (event.newDrink != null) {
newState.add(event.newDrink);
}
yield newState;
} else if (event is DeleteDrink) {
List<Drink> newState = List.from(state);
newState.removeAt(event.drinkIndex);
yield newState;
} else if (event is UpdateDrink) {
List<Drink> newState = List.from(state);
newState[event.drinkIndex] = event.newDrink;
yield newState;
}
}
}
片段:
body: BlocProvider(
create: (BuildContext context) => DrinkBloc(),
child: Column(children: [
Row(
我现在遇到的错误基本上是当我点击按钮添加饮料时('Drinks' 旁边的按钮)
No ancestor could be found starting from the context that was passed to BlocProvider.of<DrinkBloc>().
The context used was: DrinkForm(state: _DrinkFormState#5d9c5)
BlocProvider.of() called with a context that does not contain a Bloc of type DrinkBloc.
现在看起来如何(底部有效,但上部饮料无效,可能是因为我将整个东西都包裹在 DrinkBloc 中,不知道如何更改它 )
main.dart
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return BlocProvider<FoodBloc>(
create: (context) => FoodBloc(),
child: MaterialApp(
title: 'Sqflite Tutorial',
theme: ThemeData(
primarySwatch: Colors.deepPurple,
),
home: FoodList(),
),
);
}
}
您没有providing/injecting DrinkBloc
进入小部件树。
因此,当您尝试使用 BlocConsumer 访问 DrinkBloc
bloc 时,它会尝试查找该 bloc 的祖先。因为它丢失了,它会抛出那个特定的错误 BlocProvider.of() called with a context that does not contain a Bloc of type DrinkBloc.
对于 providing/injecting Drinkbloc
你可以使用 BlocProvider
如下:
BlocProvider(
create: (BuildContext context) => BlocA(),
child: ChildA(),
);
在任何地方调用它作为 BlocConsumer 的祖先。
例如:
Scaffold(
appBar: AppBar(title: Text("FoodList")),
body: BlocProvider(
create: (BuildContext context) => DrinkBloc(),
child: Column(children: [
...
],
);
为了让 BlocConsumer 在上下文中工作,它应该知道它使用的 bloc,因此,called with a context that does not contain a Bloc of type DrinkBloc.
在 flutter_bloc 文档中,您必须像这样定义提供程序
BlocProvider(
create: (BuildContext context) => DrinkBloc(),
child: Widget("this widget's context contains DrinkBloc"),
);
因此,只需将它放在小部件树中您想要放置的位置的更高位置,并将 BlocConsumer 放在其中的任何位置。