cancel method

void cancel()

Removes all subscriptions from this composite.

A member that was cancelled on its own is skipped rather than cancelled again. Cancelling a subscription twice is a mistake in the caller and says so, but a composite holding one is not that caller: raising here would leave every member after it in the list still listening, which is the leak the composite exists to prevent -- and only in debug, since release has no assert to raise.

Implementation

void cancel() {
  assert(debugAssertNotDisposed(this, _isDisposed, 'cancel'));
  if (!_isDisposed) {
    _isDisposed = true;

    // One member that cannot let go is no reason to walk away from the ones
    // behind it, which are still listening -- the same rule the disposal of
    // a dependency group follows, and for the same reason: the leak this
    // class exists to prevent is exactly what an early exit leaves. A
    // `ChangeNotifier` cannot get here, `removeListener` on one being
    // incapable of throwing; a `Listenable` of the caller's own can.
    AsyncError? failure;

    for (final subscription in _subscriptions) {
      if (subscription._isDisposed) {
        continue;
      }

      try {
        subscription.cancel();
        // ignore: avoid_catching_errors
      } on Object catch (error, stackTrace) {
        if (failure == null) {
          failure = AsyncError(error, stackTrace);
        } else {
          // A throw carries one failure and the first has claimed it, so
          // everything behind it goes the only other way there is.
          FlutterError.reportError(
            FlutterErrorDetails(
              exception: error,
              stack: stackTrace,
              library: 'scopo',
              context: ErrorDescription(
                'while cancelling a $CompositeListenableSubscription',
              ),
            ),
          );
        }
      }
    }

    _subscriptions.clear();

    if (failure case final failure?) {
      Error.throwWithStackTrace(failure.error, failure.stackTrace);
    }
  }
}