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);
}
}
}