changenotifierProvider与ChangeNotifierProvider.value

时间:2019-08-03 06:24:56

标签: flutter frameworks provider state-management

我对这个框架很陌生,并且使用提供程序包来进行状态管理,在其中遇到了changeNotifierProviderChangeNotifierProvider.value,但是我无法区分它们的用例。

我用ChangeNotifierProvider代替了ChangeNotifierProvider.value,但没有按预期工作。

5 个答案:

答案 0 :(得分:22)

让我们逐步进行。

什么是ChangeNotifier?

扩展了ChangeNotifier的类可以在任何时候更新该类中的数据并且您想让监听者知道该更新的时间,调用notifyListeners()。通常,这是在视图模型中完成的,以通知UI根据新数据重建布局。

这里是一个例子:

class MyChangeNotifier extends ChangeNotifier {
  int _counter = 0;
  int get counter => _counter;

  void increment() {
    _counter++;
    notifyListeners();
  }
}

我在A beginner’s guide to architecting a Flutter app中写了更多有关此的内容。

什么是ChangeNotifierProvider?

ChangeNotifierProvidermany types of providersProvider package的其中之一。如果您已经有一个ChangeNotifier类(如上面的类),则可以使用ChangeNotifierProvider将其提供到UI布局中所需的位置。

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return ChangeNotifierProvider<MyChangeNotifier>(        // define it
      create: (context) => MyChangeNotifier(),              // create it
      child: MaterialApp(
        ...

          child: Consumer<MyChangeNotifier>(                // get it
            builder: (context, myChangeNotifier, child) {
              ...
                  myChangeNotifier.increment();             // use it

尤其要注意,在此行中创建了MyChangeNotifier类的新实例:

create: (context) => MyChangeNotifier(),

这是在第一次构建窗口小部件时执行的,而不是在随后的重建中完成。

那么,什么是ChangeNotifierProvider.value?

如果您已经创建了ChangeNotifierProvider.value类的实例,请使用ChangeNotifier。如果您在ChangeNotifier的{​​{1}}类的initState()方法中初始化了StatefulWidget类,则可能会发生这种情况。

在这种情况下,您将不想创建State的全新实例,因为这会浪费您已经完成的所有初始化工作。使用ChangeNotifier构造函数可以提供预先创建的ChangeNotifierProvider.value值。

ChangeNotifier

请特别注意,这里没有class _MyWidgeState extends State<MyWidge> { MyChangeNotifier myChangeNotifier; @override void initState() { myChangeNotifier = MyChangeNotifier(); myChangeNotifier.doSomeInitializationWork(); super.initState(); } @override Widget build(BuildContext context) { return ChangeNotifierProvider<MyChangeNotifier>.value( value: myChangeNotifier, // <-- important part child: ... 参数,而是create参数。那就是您传递value类实例的地方。同样,不要尝试在此处创建新实例。

答案 1 :(得分:2)

ValueNotifier和ChangeNotifier密切相关。

  

实际上,ValueNotifier是ChangeNotifier的子类,它实现   ValueListenable。

这是Flutter SDK中ValueNotifier的实现:

/// A [ChangeNotifier] that holds a single value.
///
/// When [value] is replaced with something that is not equal to the old
/// value as evaluated by the equality operator ==, this class notifies its
/// listeners.
class ValueNotifier<T> extends ChangeNotifier implements ValueListenable<T> {
  /// Creates a [ChangeNotifier] that wraps this value.
  ValueNotifier(this._value);

  /// The current value stored in this notifier.
  ///
  /// When the value is replaced with something that is not equal to the old
  /// value as evaluated by the equality operator ==, this class notifies its
  /// listeners.
  @override
  T get value => _value;
  T _value;
  set value(T newValue) {
    if (_value == newValue)
      return;
    _value = newValue;
    notifyListeners();
  }

  @override
  String toString() => '${describeIdentity(this)}($value)';
}

那么,什么时候应该使用ValueNotifier和ChangeNotifier?

  

如果您需要在简单值时重建小部件,请使用ValueNotifier   变化。如果您想进一步控制时间,请使用ChangeNotifier   notifyListeners()被调用。

答案 2 :(得分:1)

是ChangeNotifierProvider.value和create函数之间的重要区别。当您在单个列表或网格项目中使用Provider时,Flatter会在离开屏幕时删除项目,并在重新进入屏幕时重新添加项目,在这种情况下,实际发生的是Flutter重用了窗口小部件本身,而只是数据附加到它的改变。因此,Flatter回收了相同的小部件,不会破坏它 并重新创建它。当我们将Provider与create函数一起使用时。

ChangeNotifierProvider(
  create: (_) => new MyChangeNotifier(),
  child: ...
)

☝☝☝这里的内容随时间而变化,我们的提供商将不会接我们。

在单个列表或网格项目中,我们应使用提供者点值。

ChangeNotifierProvider.value(
  value: new MyChangeNotifier(),
  child: ...
)

答案 3 :(得分:0)

官方文档有帮助吗?

  

DO 使用ChangeNotifierProvider.value提供现有的 series: <LineSeries<SalesData, String>>[ LineSeries<SalesData, String>( dataSource: <SalesData>[ SalesData('Jan', 35), SalesData('Feb', 28), SalesData('Mar', 34), SalesData('Apr', 32), SalesData('May', 40) ],

ChangeNotifier
  

不要使用默认构造函数重用现有的ChangeNotifierProvider.value( value: variable, child: ... )

ChangeNotifier

也请作者检查一下Github issue

答案 4 :(得分:0)

基本上,带有builder(Provider v3)或create(Provider v4)参数的ChangeNotifierProvider是处置提供程序,此提供程序拥有状态源并管理其生存期。值提供者仅引用状态源,但不管理其生存期。 在处理提供程序时,builder或create参数提供了用于创建状态源的功能。在值提供程序中,有一个值参数,该参数引用状态源,您负责根据需要创建和处置状态源。