更改项目状态后如何更新列表? (Flutter和提供者)

时间:2020-07-12 19:40:07

标签: flutter dart state provider state-management

大家好,感谢您关注我的问题,

我有这个问题:我有一个项目列表,每个项目都具有收藏夹状态,并且有一个页面显示收藏夹项目。切换收藏夹状态时,我希望页面更新并删除不喜欢的项目。

尝试过ChangeNotifierProxyProvider也没有成功,状态正在更改,但是notifyListeners不会更新主列表。 我知道在应用程序中间带有一个enpty 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();
  }
}

3 个答案:

答案 0 :(得分:1)

说实话,Provider的工作方式是通过将小部件树中的数据从父级传播到子级,但是您希望子级(Item)通知父级更改(Collection)这样会使父母和子女都相互依赖(并在以后导致一些spaguetti代码)。如果对收藏夹进行的所有更改都将更新列表,那么最好将整个逻辑保留在Collection中,并将Item类保留为简单模型

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);
              })
        ],
      ),
    );
  }
}

答案 1 :(得分:0)

是否存在从列表中删除项目后列表未在视觉上更新的问题?尝试使用:

Container(
    key: UniqueKey(),
    child: CardWidget()
)

我不知道为什么会这样,但是当我遇到这个问题时这对我有用。

答案 2 :(得分:0)

尝试使用“ setState()”方法,该方法可以重建屏幕,您应该会看到所做的更改