所以我有ExploreScreen
一个启动我的 BLoC FilteredRecipesBloc的屏幕。在此屏幕内,有一个导航到新屏幕的按钮FilterScreen
。从 中FilterScreen
,我想添加一个影响两个屏幕的新事件。现在的问题是我收到此错误消息(onError Bad state: Cannot add new events after call close)。如果不使用 BlocProvider 包装 MaterialApp,这可能吗?我只想让本地集团访问两个屏幕。
探索屏幕:
class ExploreScreen extends StatefulWidget {
@override
_ExploreScreenState createState() => _ExploreScreenState();
}
class _ExploreScreenState extends State<ExploreScreen> {
FilteredRecipesBloc _filteredRecipesBloc;
@override
void initState() {
_filteredRecipesBloc = FilteredRecipesBloc(
recipeList:
(BlocProvider.of<RecipesBloc>(context).state as RecipesLoaded)
.recipeList);
super.initState();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Explore"),
),
body: BlocProvider(
create: (context) => _filteredRecipesBloc,
child: BlocBuilder<FilteredRecipesBloc, FilteredRecipesState>(
builder: (context, state) {
if (state is FilteredRecipeEmpty) {
return CategoriesScreen();
}
if (state is FilteredRecipesLoading) {
return Column(
children: <Widget>[
CircularProgressIndicator(),
IconButton(
icon: Icon(Icons.add),
onPressed: () {
_filteredRecipesBloc.add(UpdateRecipesFilter(
ingredients: ["Curry"], maxCookTime: 30));
},
),
],
);
}
if (state is FilteredRecipeLoaded) {
return ListView.builder(
itemCount: state.recipeList.length,
itemBuilder: (_, int index) {
return ImageRecipeContainer(recipe: state.recipeList[index]);
});
}
return Container();
}),
),
floatingActionButton: FloatingActionButton(
onPressed: _navigateToFilterScreen,
child: Icon(EvaIcons.funnelOutline),
heroTag: "fafdsf",
),
);
}
void _navigateToFilterScreen() {
Navigator.of(context)
.push(MaterialPageRoute<FilterScreen>(builder: (context) {
return BlocProvider.value(
value: _filteredRecipesBloc,
child: FilterScreen(_filteredRecipesBloc),
);
}));
}
@override
void dispose() {
_filteredRecipesBloc.close();
super.dispose();
}
}
过滤屏幕:
class FilterScreen extends StatefulWidget {
final FilteredRecipesBloc filteredRecipesBloc;
FilterScreen(this.filteredRecipesBloc);
@override
_FilterScreenState createState() => _FilterScreenState();
}
class _FilterScreenState extends State<FilterScreen> {
Map<String, bool> _selectedCategories = {};
Map<String, bool> _selectedIngredients = {};
@override
void initState() {
_initIngredientList();
super.initState();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text("Filter"),),
body: SingleChildScrollView(
child: Padding(
padding: const EdgeInsets.all(12.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text("Category",style: TextStyle(fontSize: 20,fontWeight: FontWeight.bold),),
ChoiceChip(
label: Text("Vegan"),
selected: _selectedCategories["vegan"] == true,
onSelected: (isActive){
setState(() {
_selectedCategories["vegan"] = isActive;
});
},
),
Text("Ingredients"),
ShowMoreChoiceChips(children: _buildIngredientChoiceChips()),
RaisedButton(onPressed: _updateFilter),
],
),
),
),
);
}
void _initIngredientList(){
List<Recipe> recipeList =
(BlocProvider.of<RecipesBloc>(context).state as RecipesLoaded).recipeList ?? [];
for(int i = 0; i < recipeList.length;i++){
for(int y = 0; y < recipeList[i].ingredientsFlat.length;y++){
_selectedIngredients[recipeList[i].ingredientsFlat[y].name] = false;
}
}
}
List<Widget> _buildIngredientChoiceChips(){
List<Widget> widgetList = [];
_selectedIngredients.forEach((key, value){
widgetList.add(ChoiceChip(label: Text(key), selected: value,onSelected: (isActive){
setState(() {
_selectedIngredients[key] = isActive;
});
},));
});
return widgetList;
}
void _updateFilter(){
List<String> ingredients = [];
_selectedIngredients.forEach((k,v){
if(v) ingredients.add(k);
});
widget.filteredRecipesBloc.add(
UpdateRecipesFilter(ingredients: ingredients.isNotEmpty ? ingredients : null));
//BlocProvider.of<FilteredRecipesBloc>(context).add(
// UpdateRecipesFilter(ingredients: ingredients.isNotEmpty ? ingredients : null),);
}
}