ChangeNotifierProvider vs ChangeNotifierProvider.value

后端 未结 4 1903
悲&欢浪女
悲&欢浪女 2020-12-17 15:24

I am quite new to this framework and working on state management using provider package where I come across ChangeNotifierProvider and ChangeNotifierProvi

相关标签:
4条回答
  • 2020-12-17 15:58

    ValueNotifier and ChangeNotifier are closely related.

    In fact, ValueNotifier is a subclass of ChangeNotifier that implements ValueListenable.

    This is the implementation of ValueNotifier in the Flutter SDK:

    /// 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)';
    }
    

    So, when should we use ValueNotifier vs ChangeNotifier?

    Use ValueNotifier if you need widgets to rebuild when a simple value changes. Use ChangeNotifier if you want more control on when notifyListeners() is called.

    0 讨论(0)
  • 2020-12-17 16:02

    Let's take this in steps.

    What is ChangeNotifier?

    A class that extends ChangeNotifier can call notifyListeners() any time data in that class has been updated and you want to let a listener know about that update. This is often done in a view model to notify the UI to rebuild the layout based on the new data.

    Here is an example:

    class MyChangeNotifier extends ChangeNotifier {
      int _counter = 0;
      int get counter => _counter;
    
      void increment() {
        _counter++;
        notifyListeners();
      }
    }
    

    I wrote more about this in A beginner’s guide to architecting a Flutter app.

    What is ChangeNotifierProvider?

    ChangeNotifierProvider is one of many types of providers in the Provider package. If you already have a ChangeNotifier class (like the one above), then you can use ChangeNotifierProvider to provide it to the place you need it in the UI layout.

    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
    

    Note in particular that a new instance of the MyChangeNotifier class was created in this line:

    create: (context) => MyChangeNotifier(),
    

    This is done one time when the widget is first built, and not on subsequent rebuilds.

    What is ChangeNotifierProvider.value for then?

    Use ChangeNotifierProvider.value if you have already created an instance of the ChangeNotifier class. This type of situation might happen if you had initialized your ChangeNotifier class in the initState() method of your StatefulWidget's State class.

    In that case, you wouldn't want to create a whole new instance of your ChangeNotifier because you would be wasting any initialization work that you had already done. Using the ChangeNotifierProvider.value constructor allows you to provide your pre-created ChangeNotifier value.

    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: ... 
    

    Take special note that there isn't a create parameter here, but a value parameter. That's where you pass in your ChangeNotifier class instance. Again, don't try to create a new instance there.

    0 讨论(0)
  • 2020-12-17 16:02

    Does the official documentation help?

    DO use ChangeNotifierProvider.value to provider an existing ChangeNotifier:

    ChangeNotifierProvider.value(
      value: variable,
      child: ...
    )
    

    DON'T reuse an existing ChangeNotifier using the default constructor.

    ChangeNotifierProvider(
      builder: (_) => variable,   
      child: ... 
    )
    

    Also check out this Github issue from the author about this.

    0 讨论(0)
  • 2020-12-17 16:02

    Is an important difference between ChangeNotifierProvider.value and with the create function. When you're using Provider in a single list or grid item, Flatter removes items when they leave the screen and re adds them when they reentered the screen in such situations what actually happens is that the widget itself is reused by Flutter and just the data that's attached to it changes. So Flatter recycles the same widget it doesn't destroy it and recreate it. when we are using Provider with the create function.

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

    ☝☝☝ here which is content changes over time and our provider won't pick us up.

    In a single list or grid item, we should use Provider dot value.

    ChangeNotifierProvider.value(
      value: new MyChangeNotifier(),
      child: ...
    )
    
    0 讨论(0)
提交回复
热议问题