【问题标题】:How can I update the list after changing an Item status? (Flutter and Provider)更改项目状态后如何更新列表? (颤振和提供者)
【发布时间】:2020-07-12 19:40:07
【问题描述】:

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

尝试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();
  }
}

【问题讨论】:

    标签: flutter dart state provider state-management


    【解决方案1】:

    老实说,Provider 的工作方式是将数据沿着小部件树从父级传播到子级,但您希望子级 (Item) 通知父级更改 (Collection),这会使父母和孩子都相互依赖(稍后会导致一些意大利面条代码)。如果对收藏夹的每次更改都会更新列表,那么最好将整个逻辑保留在 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);
                  })
            ],
          ),
        );
      }
    }
    

    【讨论】:

      【解决方案2】:

      问题是从列表中删除项目后列表没有在视觉上更新吗?尝试使用:

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

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

      【讨论】:

      • 它不起作用。列表本身正在更新,如果我进行热重载,它会显示更改。当我调用 notifyListeners 时它不会重建。
      【解决方案3】:

      尝试使用 'setState()' 方法,重建你的屏幕,你应该会看到变化

      【讨论】:

      • 这个问题不仅仅是更新当前屏幕,如果在其他页面中修改了值并且您返回上一页,setState不会帮助您
      猜你喜欢
      • 2022-01-18
      • 1970-01-01
      • 2022-11-15
      • 2021-06-18
      • 2020-08-04
      • 2022-01-20
      • 2021-11-19
      • 2021-05-23
      • 2021-11-01
      相关资源
      最近更新 更多