watch<S extends OrbitStore> method

void watch<S extends OrbitStore>(
  1. OrbitStoreRef<S> storeRef,
  2. void onChange(
    1. S store
    )
)

Watches another global store and executes onChange whenever it notifies. Automatically unsubscribes when this store is disposed.

onChange may be synchronous or async. Errors from both sync throws and unhandled async rejections are routed to FlutterError.reportError rather than crashing the notifying store or silently dropping them.

Implementation

void watch<S extends OrbitStore>(
  OrbitStoreRef<S> storeRef,
  void Function(S store) onChange,
) {
  if (_disposed) return;
  final other = storeRef();
  if (other._disposed) return; // Don't attach to an already-disposed store
  final listener = () {
    if (_disposed) return;
    try {
      // Invoke via dynamic so we can inspect the runtime return value:
      // the public API is void Function(S) for type safety, but a user
      // may pass an async closure (Future<void> is assignable to void).
      // Capturing the dynamic result lets us attach a catchError to any
      // returned Future without triggering a use_of_void_result error.
      // ignore: avoid_dynamic_calls
      final dynamic result = (onChange as dynamic)(other);
      if (result is Future<void>) {
        result.catchError((Object exception, StackTrace stackTrace) {
          FlutterError.reportError(FlutterErrorDetails(
            exception: exception,
            stack: stackTrace,
            library: 'orbit',
            context: ErrorDescription(
                'inside async watch callback on $runtimeType '
                'watching ${other.runtimeType}'),
          ));
        });
      }
    } catch (exception, stackTrace) {
      FlutterError.reportError(FlutterErrorDetails(
        exception: exception,
        stack: stackTrace,
        library: 'orbit',
        context: ErrorDescription('inside watch callback on $runtimeType '
            'watching ${other.runtimeType}'),
      ));
    }
  };
  other.addListener(listener);
  _watchDisposers.add(() => other.removeListener(listener));
}