diff --git a/mobx/CHANGELOG.md b/mobx/CHANGELOG.md index 52380b9d..3eabc66a 100644 --- a/mobx/CHANGELOG.md +++ b/mobx/CHANGELOG.md @@ -1,3 +1,7 @@ +## 2.2.2 + +- Fix [#956]((https://github.com/mobxjs/mobx.dart/issues/956)): ObservableSet` and `ObservableMap` should not notify all listeners when `observe` with fireImmediately. by [@amondnet](https://github.com/amondnet) in [#962](https://github.com/mobxjs/mobx.dart/pull/962) + ## 2.2.1 - Reduces unnecessary iterations while using `Iterables` with `addAll`, `insertAll`, `replaceRange`, `setAll` and `setRange` methods. [#942](https://github.com/mobxjs/mobx.dart/pull/942). diff --git a/mobx/lib/src/api/observable_collections/observable_map.dart b/mobx/lib/src/api/observable_collections/observable_map.dart index be1cd7d4..e5f31281 100644 --- a/mobx/lib/src/api/observable_collections/observable_map.dart +++ b/mobx/lib/src/api/observable_collections/observable_map.dart @@ -219,11 +219,17 @@ class ObservableMap @override Dispose observe(MapChangeListener listener, {bool fireImmediately = false}) { - final dispose = _listeners.add(listener); if (fireImmediately == true) { - _map.forEach(_reportAdd); + _map.forEach((key, value) { + listener(MapChange( + type: OperationType.add, + key: key, + newValue: value, + object: this, + )); + }); } - return dispose; + return _listeners.add(listener); } } diff --git a/mobx/lib/src/api/observable_collections/observable_set.dart b/mobx/lib/src/api/observable_collections/observable_set.dart index 65cc56e8..40944545 100644 --- a/mobx/lib/src/api/observable_collections/observable_set.dart +++ b/mobx/lib/src/api/observable_collections/observable_set.dart @@ -153,11 +153,16 @@ class ObservableSet @override Dispose observe(SetChangeListener listener, {bool fireImmediately = false}) { - final dispose = _listeners.add(listener); if (fireImmediately == true) { - _set.forEach(_reportAdd); + for (final value in _set) { + listener(SetChange( + object: this, + type: OperationType.add, + value: value, + )); + } } - return dispose; + return _listeners.add(listener); } void _reportAdd(T value) { diff --git a/mobx/lib/version.dart b/mobx/lib/version.dart index ebfac1c1..ff46c3cb 100644 --- a/mobx/lib/version.dart +++ b/mobx/lib/version.dart @@ -1,4 +1,4 @@ // Generated via set_version.dart. !!!DO NOT MODIFY BY HAND!!! /// The current version as per `pubspec.yaml`. -const version = '2.2.1'; +const version = '2.2.2'; diff --git a/mobx/pubspec.yaml b/mobx/pubspec.yaml index bbf31ca5..e8abae7b 100644 --- a/mobx/pubspec.yaml +++ b/mobx/pubspec.yaml @@ -1,5 +1,5 @@ name: mobx -version: 2.2.1 +version: 2.2.2 description: "MobX is a library for reactively managing the state of your applications. Use the power of observables, actions, and reactions to supercharge your Dart and Flutter apps." homepage: https://github.com/mobxjs/mobx.dart diff --git a/mobx/test/observable_list_test.dart b/mobx/test/observable_list_test.dart index 14fab84c..90553e53 100644 --- a/mobx/test/observable_list_test.dart +++ b/mobx/test/observable_list_test.dart @@ -103,6 +103,32 @@ void main() { expect(count, equals(2)); }); + test( + 'observe with fireImmediately should not send events to already registered listeners', + () { + final list = ObservableList.of([0]); + + var count1 = 0; + var count2 = 0; + + list + .observe((change) { + count1++; + }); + + list + .observe((change) { + count2++; + }, fireImmediately: true); + + list.add(1); + + // 0 + 1: add + expect(count1, equals(1)); + // 1 + 1: fireImmediately + add + expect(count2, equals(2)); + }); + test('observe set length works', () { // ignore: omit_local_variable_types final ObservableList list = ObservableList.of([0]); diff --git a/mobx/test/observable_map_test.dart b/mobx/test/observable_map_test.dart index b057d83e..71a99559 100644 --- a/mobx/test/observable_map_test.dart +++ b/mobx/test/observable_map_test.dart @@ -222,6 +222,20 @@ void main() { expect(changes[1].newValue, equals(1)); }); + test( + 'observe should not send changes to all listeners immediately when fireImmediately is true', + () { + final changes1 = []; + final changes2 = []; + final map = ObservableMap.of({'a': 0, 'b': 1}); + + map.observe(changes1.add); + map.observe(changes2.add, fireImmediately: true); + + expect(changes1, isEmpty); + expect(changes2, isNotEmpty); + }); + test('works when adding a null value', () { final map = ObservableMap(); map['a'] = null; diff --git a/mobx/test/observable_set_test.dart b/mobx/test/observable_set_test.dart index cf4180be..c5778463 100644 --- a/mobx/test/observable_set_test.dart +++ b/mobx/test/observable_set_test.dart @@ -86,6 +86,19 @@ void main() { expect(changes[1].value, equals(2)); }); + test( + 'observe should not send add events to all listeners when fireImmediately is true', + () { + final oset = ObservableSet.of([1, 2]); + final changes1 = >[]; + final changes2 = >[]; + oset.observe(changes1.add); + oset.observe(changes2.add, fireImmediately: true); + + expect(changes1, isEmpty); + expect(changes2, isNotEmpty); + }); + group('fires reportObserved() for read methods', () { )>{ 'union': (m) => m.union({2, 5, 6}),