我开始通过使用Provider构建简单的Todo应用程序来学习Flutter / Dart,并且遇到了状态管理问题。需要明确的是,我编写的代码可以正常工作,但似乎……错了。我找不到足够类似于我的案例的示例,无法理解解决此问题的正确方法。
This is what the app looks like
这是一份按部分划分的杂货 list (“冷冻”,“水果和蔬菜”)。每个部分都有多个项目,并显示“x of y complete”进度指示器。按下每个项目都会“完成”。GroceryItemModel
看起来像这样:
class GroceryItemModel extends ChangeNotifier {
final String name;
bool _completed = false;
GroceryItemModel(this.name);
bool get completed => _completed;
void complete() {
_completed = true;
notifyListeners();
}
}
我在
GroceryItem
小部件中使用它,如下所示:class GroceryItem extends StatelessWidget {
final GroceryItemModel model;
GroceryItem(this.model);
@override
Widget build(BuildContext context) {
return ChangeNotifierProvider.value(
value: model,
child: Consumer<GroceryItemModel>(builder: (context, groceryItem, child) {
return ListTile(
title: Text(groceryItem.name),
leading: groceryItem.completed ? Icon(Icons.check_circle, color: Colors.green) : Icon(Icons.radio_button_unchecked)
onTap: () => groceryItem.complete();
})
);
}
}
我想要的下一步是在一个部分中包含多个项目,该部分根据完成的项目跟踪完整性。
GroceryListSectionModel
看起来像这样:class GroceryListSectionModel extends ChangeNotifier {
final String name;
List<GroceryItemModel> items;
GroceryListSectionModel(this.name, [items]) {
this.items = items == null ? [] : items;
// THIS RIGHT HERE IS WHERE IT GETS WEIRD
items.forEach((item) {
item.addListener(notifyListeners);
});
// END WEIRD
}
int itemCount() => items.length;
int completedItemCount() => items.where((item) => item.completed).length;
}
我在
GroceryListSection
小部件中使用它,如下所示:class GroceryListSection extends StatelessWidget {
final GroceryListSectionModel model;
final ValueChanged<bool> onChanged;
GroceryListSection(this.model, this.onChanged);
@override
Widget build(BuildContext context) {
return ChangeNotifierProvider.value(
value: model,
child: Consumer<GroceryListSectionModel>(
builder: (context, groceryListSection, child) {
return Container(
child: ExpansionTile(
title: Text(model.name),
subtitle: Text("${groceryListSection.completedItemCount()} of ${groceryListSection.itemCount()} completed"),
children: groceryListSection.items.map((groceryItemModel) =>
GroceryItem(groceryItemModel)).toList()
)
);
}
)
);
}
}
问题:
ChangeNotifierProvider
和Consumer
似乎很奇怪。我见过的所有示例都没有做到这一点。 GroceryListSectionModel
监听所有GroceryItemModels
上的更改以使更改传播回树肯定是错误的。我看不到如何正确扩展。 有什么建议么?谢谢!
最佳答案
这不是嵌套提供程序,但是我认为在您的示例中,这是更好的方法。
每个section ("Frozen", "Fruits and Veggies")
仅定义一个ChangeNotifierProvidercomplete()
中的ItemModel
函数位于GroceryListSectionModel()
中,并且参数来自当前列表索引
class GroceryListSection extends StatelessWidget {
final GroceryListSectionModel model;
// final ValueChanged<bool> onChanged;
GroceryListSection(this.model);
@override
Widget build(BuildContext context) {
return new ChangeNotifierProvider<GroceryListSectionModel>(
create: (context) => GroceryListSectionModel(model.name, model.items),
child: new Consumer<GroceryListSectionModel>(
builder: (context, groceryListSection, child) {
return Container(
child: ExpansionTile(
title: Text(model.name),
subtitle: Text("${groceryListSection.completedItemCount()} of ${groceryListSection.itemCount()} completed"),
children: groceryListSection.items.asMap().map((i, groceryItemModel) => MapEntry(i, GroceryItem(groceryItemModel, i))).values.toList()
)
);
}
)
);
}
}
class GroceryItem extends StatelessWidget {
final GroceryItemModel model;
final int index;
GroceryItem(this.model, this.index);
@override
Widget build(BuildContext context) {
return ListTile(
title: Text(model.name),
leading: model.completed ? Icon(Icons.check_circle, color: Colors.green) : Icon(Icons.radio_button_unchecked),
onTap: () => Provider.of<GroceryListSectionModel>(context, listen: false).complete(index),
);
}
}
class GroceryListSectionModel extends ChangeNotifier {
String name;
List<GroceryItemModel> items;
GroceryListSectionModel(this.name, [items]) {
this.items = items == null ? [] : items;
}
int itemCount() => items.length;
int completedItemCount() => items.where((item) => item.completed).length;
// complete Void with index from List items
void complete(int index) {
this.items[index].completed = true;
notifyListeners();
}
}
// normal Model without ChangeNotifier
class GroceryItemModel {
final String name;
bool completed = false;
GroceryItemModel({this.name, completed}) {
this.completed = completed == null ? false : completed;
}
}
关于flutter - Flutter Provider:如何通知模型包含的模型发生了更改?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61298116/