'Flutter Riverpod ref.read() vs ref.listen() vs ref.watch()
After reading the documentation, it did not explain very well what ref.read()
, ref.watch()
, and ref.listen()
is.
The questions I have are as follows:
- What is the purpose and difference between these functions?
- Where and where not can I use these functions?
- When should I use these functions?
Solution 1:[1]
What is the purpose and difference between these functions?
read()
Use read
to the get the value of/in provider just once (one-time read)
watch()
Use watch
to the get the value of/in provider the first time and every time the value changes (see it like you're subscribing to the provider, so you get notified any time there's a change)
listen()
listen
is similar to watch
. The main difference is the return type.
watch
returns the new value directly, listen
returns a void
but gives access to the new value and the old value with a callback (See examples below)
Where and where not can I use these functions?
You can use read
in places like initState
, callbacks like onPressed
etc. watch
and listen
should not be called asynchronously, like inside an onPressed
of an ElevatedButton. Nor should it be used inside initState
and other State life-cycles.
As Kaan Taha Köken pointed out:
AVOID using [read] for creating widgets with a value that never changes and CONSIDER using [Provider] or
select
for filtering unwanted rebuilds.
When should I use these functions?
read()
Use read
when you want to value of the provider only once.
watch()
Use watch
when you want to always get the value.
Example: Counter app with StateProvider
final counterProvider = StateProvider((ref) => 0);
class HomePage extends ConsumerWidget {
const HomePage({Key? key}) : super(key: key);
@override
Widget build(BuildContext context, WidgetRef ref) {
final counter = ref.watch(counterProvider);
ref.listen(
counterProvider,
(previous, next) {
print("The new value is $next");
if (next == 5) {
print("I just reached 5");
}
},
);
return Scaffold(
body: Center(
child: Text(
counter.toString(),
),
),
floatingActionButton: FloatingActionButton(
onPressed: () {
ref.read(counterProvider.state).state += 1;
},
),
);
}
}
The example above shows the use of watch
, read
and listen
.
- We're
watch
ing thecounter
value so it gets updated in the UI anytime there is a change. - We're
listen
ing to thecounter
to print the updated value and printI've reached 5
when it is 5. - To increment the value, we
read
the provider state and add1
when theFloatingActionButton
is pressed.
Solution 2:[2]
Riverpod is a complete rewrite of the Provider package i have not used Riverpod yet but as provider experience i will share some details
read()
is used to listen one time; it may be function or variables
watch()
is for listen more time ie, listen true; so when the data changes is will be listen and adopt new value
lisen()
The main difference between watch and lisen is that, rather than rebuilding the widget/provider if the listened to provider changes, using ref.listen will instead call a custom function.
That can be useful for performing actions when a certain change happens, such as showing a snackbar when an error happens.
for more information take a look at this
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | |
Solution 2 | Akbar Masterpadi |