listen<T> method

  1. @override
void Function() listen<T>(
  1. ProviderListenable<T> listenable,
  2. void listener(
    1. T? previous,
    2. T value
    ), {
  3. bool fireImmediately = false,
  4. void onError(
    1. Object error,
    2. StackTrace stackTrace
    )?,
})
override

Listen to a provider and call listener whenever its value changes.

Listeners will automatically be removed when the provider rebuilds (such as when a provider listeneed with watch changes).

Returns a function that allows cancelling the subscription early.

  • fireImmediately can be optionally passed to tell Riverpod to immediately call the listener with the current value. Defaults to false.

Implementation

@override
void Function() listen<T>(
  ProviderListenable<T> listenable,
  void Function(T? previous, T value) listener, {
  bool fireImmediately = false,
  void Function(Object error, StackTrace stackTrace)? onError,
}) {
  _assertNotOutdated();
  assert(!_debugIsRunningSelector, 'Cannot call ref.read inside a selector');

  if (listenable is _ProviderSelector<Object?, T>) {
    return listenable._elementListen(
      this,
      listener,
      fireImmediately: fireImmediately,
      onError: onError,
    );
  }

  final provider = listenable as ProviderBase<T>;
  onError ??= _fallbackOnErrorForProvider(provider);
  assert(_debugAssertCanDependOn(provider), '');

  // TODO remove by passing the a debug flag to `listen`
  final element = container.readProviderElement(provider);
  // TODO test flush
  element.flush();

  if (fireImmediately) {
    handleFireImmediately(
      element.getState()!,
      listener: listener,
      onError: onError,
    );
  }

  // TODO(rrousselGit) test

  final sub = _ProviderListener._(
    listenedElement: element,
    dependentElement: this,
    listener: (prev, value) => listener(prev as T?, value as T),
    onError: onError,
  );

  element._subscribers.add(sub);
  _subscriptions.add(sub);

  return () {
    _subscriptions.remove(sub);
    // this will remove element._subscribers
    sub.close();
  };
}