'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 watching the counter value so it gets updated in the UI anytime there is a change.
  • We're listening to the counter to print the updated value and print I've reached 5 when it is 5.
  • To increment the value, we read the provider state and add 1 when the FloatingActionButton 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