Flutter Provider select - 如何处理复杂的返回类型,如 List 或 Map

Posted

技术标签:

【中文标题】Flutter Provider select - 如何处理复杂的返回类型,如 List 或 Map【英文标题】:Flutter Provider select - How do handle complex returned type like List or Map 【发布时间】:2021-05-31 03:12:05 【问题描述】:

我正在尝试使用flutter provider,但当返回的类型是具有未更改引用的复杂对象(如MapList)时,我遇到了context.select() 的问题。 即使我通知模型的侦听器,我的小部件也不会重建,我怀疑这是因为我正在修改我的对象。

这是一个简单的重现代码

class MyModel extends ChangeNotifier 
  final list = <int>[0, 1, 2, 3, 4, 5];

  void push() 
    // Here I modify the list in place, and even when I call `notifyListeners()`, `MyWidget` won't rebuild
    list.add(list.length); 
    notifyListeners();
  


class MyScreen extends StatelessWidget 
  @override
  Widget build(BuildContext context) 
    return ChangeNotifierProvider<MyModel>(
      create: (_) => MyModel(),
      child: MyWidget(),
    );
  


class MyWidget extends StatefulWidget 
  @override
  _MyWidgetState createState() => _MyWidgetState();


class _MyWidgetState extends State<MyWidget> 
  @override
  Widget build(BuildContext context) 
    // It is not rebuilt when the list is modified, the widget is rebuilt if I add
    // context.select<MyModel, int>((myModel) => myModel.list.length);
    // for example
    // I suspect it is because the reference of `myModel.list` didn't change
    final list = context.select<MyModel, List<int>>((myModel) => myModel.list);

    return Container(
      child: Column(
        children: [
          Text(list.join(', ')),
          TextButton(
            child: const Text('Add'),
            onPressed: () 
              context.read<MyModel>().push();
              // setState(() ); <- I could force the rebuild here too
            ,
          ),
        ],
      ),
    );
  

当我单击按钮 Add 时,list 会更新,但我的小部件并未重建。 例如,我可以在onPressed 末尾调用setState(() ) 来强制重建,但我不想这样做。


处理这个问题的最佳方法是什么?

【问题讨论】:

【参考方案1】:

您的list 应该是不可变的:

class MyModel extends ChangeNotifier 
  List<int> list = <int>[0, 1, 2, 3, 4, 5];

  void push() 
    list = [...list, list.length];
    notifyListeners();
  

否则,对象引用相同,Widget不会重建。

【讨论】:

以上是关于Flutter Provider select - 如何处理复杂的返回类型,如 List 或 Map的主要内容,如果未能解决你的问题,请参考以下文章

flutter_bloc/provider RepositoryProvider vs Provider

Flutter - Provider - 如何根据 Provider 的值更改 UI?

Flutter:如何用 Provider 播放动画?

Flutter之跨组件状态共享Provider剖析

Flutter之跨组件状态共享Provider剖析

Flutter 中的 Bloc Provider 和 Normal Provider 有啥区别?