watch<T> abstract method

T watch<T>(
  1. AlwaysAliveProviderBase<Object?, T> provider
)

Obtains the state of a provider and cause the state to be re-evaluated when that provider emits a new value.

Using watch allows supporting the scenario where we want to re-create our state when one of the object we are listening to changed.

This method should be your go-to way to make a provider read another provider – even if the value exposed by that other provider never changes.

Use-case example: Sorting a todo-list

Consider a todo-list application. We may want to implement a sort feature, to see the uncompleted todos first.
We will want to create a sorted list of todos based on the combination of the unsorted list and a sort method (ascendant, descendant, ...), both of which may change over time.

In this situation, what we do not want to do is to sort our list directly inside the build method of our UI, as sorting a list can be expensive. But maintaining a cache manually is difficult and error prone.

To solve this problem, we could create a separate Provider that will expose the sorted list, and use watch to automatically re-evaluate the list only when needed.

In code, this may look like:

final sortProvider = StateProvider((_) => Sort.byName);
final unsortedTodosProvider = StateProvider((_) => <Todo>[]);

final sortedTodosProvider = Provider((ref) {
  // listen to both the sort enum and the unfiltered list of todos
  final sort = ref.watch(sortProvider);
  final todos = ref.watch(unsortedTodosProvider);

  // Creates a new sorted list from the combination of the unfiltered
  // list and the filter type.
  return [...todos].sort((a, b) { ... });
});

In this code, by using Provider + watch:

  • if either sortProvider or unsortedTodosProvider changes, then sortedTodosProvider will automatically be recomputed.
  • if multiple widgets depends on sortedTodosProvider the list will be sorted only once.
  • if nothing is listening to sortedTodosProvider, then no sort if performed.

Implementation

T watch<T>(AlwaysAliveProviderBase<Object?, T> provider);