select<Selected> method Null safety

ProviderListenable<Selected> select<Selected>(
  1. Selected selector(
    1. Listened value
    )
)

Partially listen to a provider.

Note: This method of listening to an object is currently only supported by useProvider 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 useProvider/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, ScopedReader watch) {
  final age = useProvider(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, ScopedReader watch) {
  final isAdult = useProvider(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

ProviderListenable<Selected> select<Selected>(
  Selected Function(Listened value) selector,
) {
  return ProviderSelector<Listened, Selected>(
    provider: this,
    selector: selector,
  );
}