更改项目状态后如何更新列表? (颤动和提供者)
How can I update the list after changing an Item status? (Flutter and Provider)
我有这个问题:我有一个项目列表,每个项目都有一个收藏状态,并且我有一个显示收藏项目的页面。我希望页面在切换收藏夹状态时更新并删除 non-favorite 项目。
尝试 ChangeNotifierProxyProvider
也没有成功,状态正在改变,但 notifyListeners 没有更新主列表。
我知道在应用程序中间使用空的 setState
来触发刷新的技巧,但我知道有一个我不知道的涉及 Provider 的更简洁的方法。
这是代码(我写的越短越好)
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return ChangeNotifierProvider(
create: (context) => Collection(),
builder: (context, child) => MaterialApp(
home: MyHomePage(),
),
);
}
}
class MyHomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
final _list = Provider.of<Collection>(context).favItems;
return Scaffold(
appBar: AppBar(
title: Text("Test"),
),
body: Container(
child: ListView.builder(
itemCount: _list.length,
itemBuilder: (_, index) => ChangeNotifierProvider.value(
value: _list[index],
child: CardWidget(),
),
),
),
);
}
}
class CardWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
final _item = Provider.of<Items>(context);
return Card(
child: Row(
children: <Widget>[
Text(_item.name),
IconButton(
icon:
_item.favourite ? Icon(Icons.star) : Icon(Icons.star_border),
onPressed: () {
_item.toggleFavourite();
})
],
),
);
}
}
class Collection with ChangeNotifier {
List<Items> _items = [
Items(name: "a", favourite: true),
Items(name: "b", favourite: true),
Items(name: "c", favourite: true),
];
List<Items> get favItems =>
[..._items].where((element) => element.favourite == true).toList();
}
class Items with ChangeNotifier {
String name;
bool favourite;
Items({this.name, this.favourite});
toggleFavourite() {
favourite = !favourite;
notifyListeners();
}
}
问题是尽管从列表中删除了项目,但列表没有在视觉上更新吗?尝试使用:
Container(
key: UniqueKey(),
child: CardWidget()
)
我不知道它为什么有效,但当我遇到这个问题时它对我有用。
尝试使用 'setState()' 重建屏幕的方法,您应该会看到变化
老实说,Provider 的工作方式是沿着小部件树传播数据,从 parent 到 children,但是您想要 child (Item
) 通知 parent 更改 (Collection
) 并且这将使 parent 和 children 相互依赖(并且稍后会导致一些意大利面条代码)。如果对收藏夹的每次更改都会更新列表,那么最好只将整个逻辑保留在 Collection
中并将 Item
class 保留为简单模型
class Collection with ChangeNotifier {
List<Items> _items = [
Items(name: "a", favourite: true),
Items(name: "b", favourite: true),
Items(name: "c", favourite: true),
];
List<Items> get favItems =>
[..._items].where((element) => element.favourite == true).toList();
toggleFavourite(Item item) {
int index = _items.indexWhere((element) => element.name == item.name);
_items[index].favourite = !_items[index].favourite;
notifyListeners();
}
}
class Items { //simple Model class
String name;
bool favourite;
Items({this.name, this.favourite});
}
class MyHomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
final _list = context.select((Collection list) => list.favItems);
//to update only if list is different
return Scaffold(
appBar: AppBar(
title: Text("Test"),
),
body: Container(
child: ListView.builder(
itemCount: _list.length,
itemBuilder: (_, index) => CardWidget(_list[index])
),
),
);
}
}
class CardWidget extends StatelessWidget {
final Item _item;
CardWidget(this._item);
@override
Widget build(BuildContext context) {
return Card(
child: Row(
children: <Widget>[
Text(_item.name),
IconButton(
icon:
_item.favourite ? Icon(Icons.star) : Icon(Icons.star_border),
onPressed: () {
Provider.of<Collection>(context, listen: false).toggleFavourite(_item);
})
],
),
);
}
}
我有这个问题:我有一个项目列表,每个项目都有一个收藏状态,并且我有一个显示收藏项目的页面。我希望页面在切换收藏夹状态时更新并删除 non-favorite 项目。
尝试 ChangeNotifierProxyProvider
也没有成功,状态正在改变,但 notifyListeners 没有更新主列表。
我知道在应用程序中间使用空的 setState
来触发刷新的技巧,但我知道有一个我不知道的涉及 Provider 的更简洁的方法。
这是代码(我写的越短越好)
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return ChangeNotifierProvider(
create: (context) => Collection(),
builder: (context, child) => MaterialApp(
home: MyHomePage(),
),
);
}
}
class MyHomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
final _list = Provider.of<Collection>(context).favItems;
return Scaffold(
appBar: AppBar(
title: Text("Test"),
),
body: Container(
child: ListView.builder(
itemCount: _list.length,
itemBuilder: (_, index) => ChangeNotifierProvider.value(
value: _list[index],
child: CardWidget(),
),
),
),
);
}
}
class CardWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
final _item = Provider.of<Items>(context);
return Card(
child: Row(
children: <Widget>[
Text(_item.name),
IconButton(
icon:
_item.favourite ? Icon(Icons.star) : Icon(Icons.star_border),
onPressed: () {
_item.toggleFavourite();
})
],
),
);
}
}
class Collection with ChangeNotifier {
List<Items> _items = [
Items(name: "a", favourite: true),
Items(name: "b", favourite: true),
Items(name: "c", favourite: true),
];
List<Items> get favItems =>
[..._items].where((element) => element.favourite == true).toList();
}
class Items with ChangeNotifier {
String name;
bool favourite;
Items({this.name, this.favourite});
toggleFavourite() {
favourite = !favourite;
notifyListeners();
}
}
问题是尽管从列表中删除了项目,但列表没有在视觉上更新吗?尝试使用:
Container(
key: UniqueKey(),
child: CardWidget()
)
我不知道它为什么有效,但当我遇到这个问题时它对我有用。
尝试使用 'setState()' 重建屏幕的方法,您应该会看到变化
老实说,Provider 的工作方式是沿着小部件树传播数据,从 parent 到 children,但是您想要 child (Item
) 通知 parent 更改 (Collection
) 并且这将使 parent 和 children 相互依赖(并且稍后会导致一些意大利面条代码)。如果对收藏夹的每次更改都会更新列表,那么最好只将整个逻辑保留在 Collection
中并将 Item
class 保留为简单模型
class Collection with ChangeNotifier {
List<Items> _items = [
Items(name: "a", favourite: true),
Items(name: "b", favourite: true),
Items(name: "c", favourite: true),
];
List<Items> get favItems =>
[..._items].where((element) => element.favourite == true).toList();
toggleFavourite(Item item) {
int index = _items.indexWhere((element) => element.name == item.name);
_items[index].favourite = !_items[index].favourite;
notifyListeners();
}
}
class Items { //simple Model class
String name;
bool favourite;
Items({this.name, this.favourite});
}
class MyHomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
final _list = context.select((Collection list) => list.favItems);
//to update only if list is different
return Scaffold(
appBar: AppBar(
title: Text("Test"),
),
body: Container(
child: ListView.builder(
itemCount: _list.length,
itemBuilder: (_, index) => CardWidget(_list[index])
),
),
);
}
}
class CardWidget extends StatelessWidget {
final Item _item;
CardWidget(this._item);
@override
Widget build(BuildContext context) {
return Card(
child: Row(
children: <Widget>[
Text(_item.name),
IconButton(
icon:
_item.favourite ? Icon(Icons.star) : Icon(Icons.star_border),
onPressed: () {
Provider.of<Collection>(context, listen: false).toggleFavourite(_item);
})
],
),
);
}
}