Riverpod is built on top of Provider, which is essentially fulfilled the lackings of Provider.
Lets first understand the problem with Provider:
-
Provider is entirely based on InheritedWidget. in other words, it depends on the widget tree. So, we can't use it outside the widget tree.
-
On the other hand Riverpod does not depend on the widget tree. We declared it globally and can use it anywhere in the app.
-
It is more like a global variable. We can use it anywhere in the app.
-
Another benefit of Riverpod i would like to mention is, we can use a riverpod provider inside another riverpod provider. (which is not possible in Provider)
The first step is to add the latest version of flutter_riverpod
as a dependency to our pubspec.yaml
file:
dependencies:
flutter:
sdk: flutter
flutter_riverpod: ^2.3.1
Once Riverpod is installed, we have to wrap our root widget with a ProviderScope:
- Provider
- Consumer
Provider
is used to provide/supply the data to the Consumer
widget. So that, we can show the data in the UI.
1. Provider:
- This is Read Only, we can't change its value.
- It is a simple state object
2. StateProvider:
- This is almost like `Provider`, but gives us more freedom and ability to change which is lackings in `Provider` .
- It is a simple state object
3. FutureProvider
- This is used to fetch data from the server / API call.
4. StreamProvider
- This is used fot continous data fetching like time data which is continous in entire time.
5. ChnageNotifierProvider [mutable]
- This is highly discouraged to use in riverpod official doc. (doc link: https://riverpod.dev/docs/concepts/providers)
6. StateNotifierProvider [immutable]
- instead of using ChangeNotifierProvider, we can use StateNotifierProvider.
- still we can change the state, but in a immutable way.
7. AsyncNotifierProvider [New in Riverpod 2.0]
8. NotifierProvider [New in Riverpod 2.0]
This Differences are confusing at least for me when i explore those providers in first time. So, i will try to explain what i understood so far.
-
Provider
andStateProvider
returns a simple dart data type (int, double, bool, String, List,...) -
Whereas,
ChnageNotifierProvider
andStateNotifierProvider
returns aclass
and the cluss which returned must have to extendChnageNotifier
,StateNotifier
respectively. -
So in order to use the
Provider
andStateProvider
, we dont have to write any class. But for theChnageNotifierProvider
andStateNotifierProvider
, you must have to write and extends.
Provider
andStateProvider
declaration:
-
if we look carefully in above two examples we could see that, in
StateNotifierProvider
we don't have to to callnotifyListener()
everytime we chnage the state. This is the beauty ofStateNotifierProvider
.
Consumer
will watch/monitoring the provided data and eventually rebuild the whole widget tree/consumed widget only; if any data (i.e. state) is changed.
a simple provider which returns a int value
final counterProvider = Provider<int>((ref) => 10);
This is made of three things:
- The declaration:
final counterProvider
is the global variable that we will use to read the state of the provider. - The provider: Provider tells us what kind of provider we're using (more on this below), and the type of the state it holds.
- A function that emmits / providing the state: This gives us a
ref
parameter that we can use toread other providers
, perform some custom dispose logic, and more.
All Flutter widgets have a BuildContext object that we can use to access things inside the widget tree (such as Theme.of(context)).
Unlike, Riverpod providers live outside the widget tree and to read them we need an additional ref object. So, when we have to communicates with providers we have to have a ref
object which is a type of WidgetRef
long story short: if we have a ref
object we can access any riverpod provider throughout our apps.