flutter - Flutter Provider:如何通知模型包含的模型发生了更改?

标签 flutter dart state-management flutter-provider

我开始通过使用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()
              )
          );
        }
      )
    );
  }
}

问题:
  • 两个小部件中都有ChangeNotifierProviderConsumer似乎很奇怪。我见过的所有示例都没有做到这一点。
  • GroceryListSectionModel监听所有GroceryItemModels上的更改以使更改传播回树肯定是错误的。我看不到如何正确扩展。

  • 有什么建议么?谢谢!

    最佳答案

    这不是嵌套提供程序,但是我认为在您的示例中,这是更好的方法。

    每个section ("Frozen", "Fruits and Veggies")仅定义一个ChangeNotifierProvider
    complete()中的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/

    相关文章:

    json - 解析嵌套的JSON对象波动

    firebase - Flutter 细节搜索功能

    android - 为什么 Flutter 只能以 super 用户身份运行?

    dart - 有没有一种方法可以使用我的刷新指示器在错误快照之后刷新 future builder

    string - 如何在 Dart 语言中按字母顺序对字符串列表进行排序?

    angular - NgRx 和 localStorage 的结合

    flutter - 如何在 Flutter 应用程序的 initState 期间使用来自 Provider 的数据

    flutter - 在容器 flutter 处制作渐变效果,

    flutter - 处理后无法安装 MaterialPageRoute<void>

    flutter - Flutter Bloc:更新状态不会重新调用BlocBuilder