【问题标题】:Why does ChangeNotifierProvider exist?为什么 ChangeNotifierProvider 存在?
【发布时间】:2021-12-10 11:17:51
【问题描述】:

根据这里的 Flutter 文档 (https://flutter.dev/docs/development/data-and-backend/state-mgmt/simple),

控制状态管理的一种方法是在其后代之一是 Consumer 时使用 ChangeNotifierProvider(或 InheritedWidget),当底层 ChangeNotifier 更改时会重新构建该 Consumer。 Flutter 的团队在官方 youtube Flutter 频道上重申了这种方法。

但是,这意味着某些业务逻辑元素 (ChangeNotifier) 现在是 Widget 树的一部分(否则就是关于 UI 的外观)。所以我不明白为什么这些类(ChangeNotifierProvider、InheritedWidget、Consumer)甚至存在。

特别是,为什么以下方法不是更好的:

-业务逻辑是一个单例和一个 ChangeNotifier。

-而不是 Provider(...),根据业务逻辑对每个 Widget 执行以下操作:

BusinessLogicSingleton.instance.addListener(() {

      setState(() {

      });

在 initState(...).

我在这里错过了什么?

【问题讨论】:

    标签: flutter design-patterns flutter-change-notifier


    【解决方案1】:

    您确实可以这样做,但是您还必须记住在 dispose 时关闭侦听器。提供者会自动处理。

    【讨论】:

    • 有趣的地方。由于所有这些小部件(initState 和 dispose)的代码看起来都一样,如果 Flutter 团队将添加对此的支持(因为忘记在 dispose 时不听会很糟糕),那么这种方法在那个时候会有什么劣势?
    • Dart 不提供析构函数回调。所以 dispose 和 close 的东西必须由用户代码在适当的地方处理。
    【解决方案2】:

    您打算如何在无状态小部件中设置状态?同样按照您建议的方法,您将使用 setstate 重建整个小部件,而如果您要使用消费者,即使对于复杂的小部件也只构建特定部分。

    【讨论】:

    • 您的观点可能是有效的,但为了让一切清楚,我将分享为什么我仍然不完全理解: 1. 根据定义,依赖于 ChangeNotifier 数据的 Widget 依赖于某些状态我们的业务逻辑......因此,使其有状态是合乎逻辑的恕我直言。 2. 您可以将较大的 Widget 分解成较小的部分,这与 Consumer 的建议完全相同,您可以以完全相同的方式滥用。
    • 如果可以,请查看我的答案 - 您可以在无状态小部件中以及任何小部件中使用此小部件,这样您就不必重建整个东西。
    【解决方案3】:

    我认为将 ChangeNotifier 作为小部件树的一部分是有好处的。您需要问自己:Widget Tree 的哪些功能可以使 ChangeNotifier 受益?或者更确切地说 - 通过使用 Widget Tree,我可以从 Singleton 获得我得到的一切吗?我可以做一些 Singleton 没有提供的东西吗?

    首先 - 如果你把你的 ChangeNotifier 放在树的高处,并且你只为你的班级创建一个 ChangeNotifier(例如 ChangeNotifier) - 你实际上有一个单例。借助 Widget Tree 逻辑的额外好处,可以处理您的 ChangeNotifier 等。

    第二 - 您可以在树的不同部分拥有多个相同类的 ChangeNotifier,实际上可以按您想要的任何方式确定 ChangeNotifier 的范围。这不是单例方法可以提供的。我不确定这是一个很好的例子 - 但想象一下您的 ShoppingCart 演示:它在树的顶部有一个 ShoppingCart ChangeNotifier 提供程序。 现在想象您销售的其中一件商品是可定制的——比如披萨。当用户选择披萨时 - 您会打开额外的屏幕,用户将在其中选择配料。现在,这个额外的屏幕可以有一个新的 ShoppingCart 实例——跟踪你添加的配料,以及购物车的所有功能——添加、删除等。这样你的模块(披萨配料选择)就变得独立了——它不会期望为它提供一个 Singleton,但它会将它自己的 ChangeNotifier 注入到树中。 使用 Singleton 方法,您需要想出另一种方法 - 扩展您的购物车以创建另一个 Singleton。不太实用。

    【讨论】:

      【解决方案4】:

      跟进这个问题,下面的超简单类为我节省了大量样板代码和不合逻辑的代码(通过 Provider 等强制 ChangeNotifier 成为 Widget 树的一部分)

      import 'package:flutter/material.dart';
      
      //A class which makes it easier to worker with change notifier without provider/consumer which looks wrong since changenotifier shouldn't be forced into widgets tree for no reason
      //eg widgets should represent UI and not business logic
      
      
      class ListenerWidget extends StatefulWidget {
        const ListenerWidget({Key? key,required ChangeNotifier notifier,required Widget Function(BuildContext) builder,void Function()? action}) : notifier=notifier,builder=builder,action=action,super(key: key);
        final Widget Function(BuildContext) builder;
        final ChangeNotifier notifier;
        final void Function()? action;
      
        @override
        _ListenerWidgetState createState() => _ListenerWidgetState();
      }
      
      class _ListenerWidgetState extends State<ListenerWidget> {
      
        void emptyListener(){
          setState(() {
      
          });
        }
      
        @override
        void initState() {
          widget.notifier.addListener(widget.action??emptyListener);
          super.initState();
        }
      
        @override
        void dispose() {
          widget.notifier.removeListener(widget.action??emptyListener);
          super.dispose();
        }
      
        @override
        Widget build(BuildContext context) {
          return widget.builder(context);
        }
      }
      

      【讨论】:

        猜你喜欢
        • 2020-07-26
        • 1970-01-01
        • 2021-11-14
        • 2019-12-11
        • 2021-01-15
        • 2021-06-06
        • 1970-01-01
        • 2010-11-12
        • 2019-05-12
        相关资源
        最近更新 更多