select<Selected> method Null safety

  1. @override
AlwaysAliveProviderListenable<Selected> select<Selected>(
  1. Selected selector(
    1. State value
    )
)
override

Partially listen to a provider.

Note: This method of listening to an object is currently only supported by ref.watch( from hooks_riverpod and ProviderContainer.listen.

The select function allows filtering unwanted rebuilds of a Widget by reading only the properties that we care about.

For example, consider the following ChangeNotifier:

class Person extends ChangeNotifier {
  int _age = 0;
  int get age => _age;
  set age(int age) {
    _age = age;
    notifyListeners();
  }

  String _name = '';
  String get name => _name;
  set name(String name) {
    _name = name;
    notifyListeners();
  }
}

final personProvider = ChangeNotifierProvider((_) => Person());

In this class, both name and age may change, but a widget may need only age.

If we used ref.watch(/Consumer as we normally would, this would cause widgets that only use age to still rebuild when name changes, which is inefficient.

The method select can be used to fix this, by explicitly reading only a specific part of the object.

A typical usage would be:

@override
Widget build(BuildContext context, WidgetRef ref) {
  final age = ref.watch(personProvider.select((p) => p.age));
  return Text('$age');
}

This will cause our widget to rebuild only when age changes.

NOTE: The function passed to select can return complex computations too.

For example, instead of age, we could return a "isAdult" boolean:

@override
Widget build(BuildContext context, WidgetRef ref) {
  final isAdult = ref.watch(personProvider.select((p) => p.age >= 18));
  return Text('$isAdult');
}

This will further optimise our widget by rebuilding it only when "isAdult" changed instead of whenever the age changes.

Implementation

@override
AlwaysAliveProviderListenable<Selected> select<Selected>(
  Selected Function(State value) selector,
) {
  return _AlwaysAliveProviderSelector<State, Selected>(
    provider: this,
    selector: selector,
  );
}