I am quite new to this framework and working on state management using provider package where I come across ChangeNotifierProvider
and ChangeNotifierProvider.value
, but I am unable to distinguish their use case.
I had used ChangeNotifierProvider
in place of ChangeNotifierProvider.value
, but it doesn't work as intended.
Firstly, ChangeNotifierProvider extends ChangeNotifier that flutter provides. Secondly, ChangeNotifierProvider listens to ChangeNotifier. Not only that, after listening to ChangeNotifier, it exposes ChangeNotifier to its descendants.
ChangeNotifierProxyProvider<MyModel, MyChangeNotifier>( create: (_) => MyChangeNotifier(), update: (_, myModel, myNotifier) => myNotifier .. update(myModel), child: ... ); In that situation, if MyModel were to update, then MyChangeNotifier will be able to update accordingly.
notifyListeners method Null safetyCall this method whenever the object changes, to notify any clients the object may have changed. Listeners that are added during this iteration will not be visited. Listeners that are removed during this iteration will not be visited after they are removed.
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.
ValueNotifier and ChangeNotifier are closely related. In fact, ValueNotifier is a subclass of ChangeNotifier that implements ValueListenable. /// A [ChangeNotifier] that holds a single value.
Most of the examples you'll see on the internets is using the ChangeNotifierProvider, and it's also the class you'll likely use most often. This class is basically a provider-wrapper over a class that implements ChangeNotifier.
If you want to pass variables to your ChangeNotifier, consider using ChangeNotifierProxyProvider. If you already have an instance of ChangeNotifier and want to expose it, you should use ChangeNotifierProvider.value instead of the default constructor. Failing to do so may dispose the ChangeNotifier when it is still in use.
Let's take this in steps.
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.
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.
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.
You can also find the usage of ChangeNotifierProvider
and ChangeNotifierProvider.value
described in the official docs: https://pub.dev/packages/provider#exposing-a-value
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With