diff --git a/packages/state_beacon_core/lib/src/extensions/wrap.dart b/packages/state_beacon_core/lib/src/extensions/wrap.dart index 7d29a10..a22a566 100644 --- a/packages/state_beacon_core/lib/src/extensions/wrap.dart +++ b/packages/state_beacon_core/lib/src/extensions/wrap.dart @@ -71,7 +71,7 @@ extension WritableWrap on BeaconWrapper { }); onDispose(() { - if (isDisposing) return; + if (isDisposing || target._guarded) return; isDisposing = true; target.dispose(); }); diff --git a/packages/state_beacon_core/lib/src/producer.dart b/packages/state_beacon_core/lib/src/producer.dart index 6000147..85e0eaf 100644 --- a/packages/state_beacon_core/lib/src/producer.dart +++ b/packages/state_beacon_core/lib/src/producer.dart @@ -95,6 +95,23 @@ abstract class Producer implements Disposable { } } + /// This is true if the beacon is guarded from being disposed by + /// its dependants. + bool _guarded = false; + + /// Prevents the beacon from being disposed by its dependants. + /// The beacon will still be disposed if its dependencies are disposed. + /// + /// ```dart + /// final number = Beacon(0)..guard(); + /// final doubled = number.map((value) => value * 2); + /// doubled.dispose(); + /// number.disposed; // false + /// ``` + void guard() { + _guarded = true; + } + /// The number of listeners subscribed to this beacon. int get listenersCount => _observers.length; diff --git a/packages/state_beacon_core/test/src/beacons/readable_test.dart b/packages/state_beacon_core/test/src/beacons/readable_test.dart index da327cd..d5fd66b 100644 --- a/packages/state_beacon_core/test/src/beacons/readable_test.dart +++ b/packages/state_beacon_core/test/src/beacons/readable_test.dart @@ -167,4 +167,26 @@ void main() { beacon.value = 1; beacon.value = 2; }); + + test('should not dispose when dependant is disposed when guarded', () { + final number = Beacon.writable(0); + + number.guard(); + + final doubled = number.map((value) => value * 2); + + doubled.dispose(); + + expect(number.isDisposed, false); + }); + + test('should dispose when dependant is disposed when not guarded', () { + final number = Beacon.writable(0); + + final doubled = number.map((value) => value * 2); + + doubled.dispose(); + + expect(number.isDisposed, true); + }); }