Commit b2c244ef authored by Ian Hickson's avatar Ian Hickson Committed by GitHub

Allow nulls in `Listenable.merge` (#7355)

This lets you use `Listenable.merge` without having to sanitize your
incoming list of change notifiers, in case your semantics are that
they are optional.
parent 27970bd8
...@@ -18,6 +18,8 @@ abstract class Listenable { ...@@ -18,6 +18,8 @@ abstract class Listenable {
/// ///
/// The list must not be changed after this method has been called. Doing so /// The list must not be changed after this method has been called. Doing so
/// will lead to memory leaks or exceptions. /// will lead to memory leaks or exceptions.
///
/// The list may contain `null`s; they are ignored.
factory Listenable.merge(List<Listenable> listenables) = _MergingListenable; factory Listenable.merge(List<Listenable> listenables) = _MergingListenable;
/// Register a closure to be called when the object notifies its listeners. /// Register a closure to be called when the object notifies its listeners.
...@@ -93,7 +95,7 @@ class ChangeNotifier extends Listenable { ...@@ -93,7 +95,7 @@ class ChangeNotifier extends Listenable {
class _MergingListenable extends ChangeNotifier { class _MergingListenable extends ChangeNotifier {
_MergingListenable(this._children) { _MergingListenable(this._children) {
for (Listenable child in _children) for (Listenable child in _children)
child.addListener(notifyListeners); child?.addListener(notifyListeners);
} }
final List<Listenable> _children; final List<Listenable> _children;
...@@ -101,7 +103,7 @@ class _MergingListenable extends ChangeNotifier { ...@@ -101,7 +103,7 @@ class _MergingListenable extends ChangeNotifier {
@override @override
void dispose() { void dispose() {
for (Listenable child in _children) for (Listenable child in _children)
child.removeListener(notifyListeners); child?.removeListener(notifyListeners);
super.dispose(); super.dispose();
} }
} }
...@@ -121,20 +121,44 @@ void main() { ...@@ -121,20 +121,44 @@ void main() {
final List<String> log = <String>[]; final List<String> log = <String>[];
final Listenable merged = new Listenable.merge(<Listenable>[source1, source2]); final Listenable merged = new Listenable.merge(<Listenable>[source1, source2]);
final VoidCallback listener = () { log.add('listener'); }; final VoidCallback listener1 = () { log.add('listener1'); };
final VoidCallback listener2 = () { log.add('listener2'); };
merged.addListener(listener); merged.addListener(listener1);
source1.notify(); source1.notify();
source2.notify(); source2.notify();
source3.notify(); source3.notify();
expect(log, <String>['listener', 'listener']); expect(log, <String>['listener1', 'listener1']);
log.clear(); log.clear();
merged.removeListener(listener); merged.removeListener(listener1);
source1.notify(); source1.notify();
source2.notify(); source2.notify();
source3.notify(); source3.notify();
expect(log, isEmpty); expect(log, isEmpty);
log.clear(); log.clear();
merged.addListener(listener1);
merged.addListener(listener2);
source1.notify();
source2.notify();
source3.notify();
expect(log, <String>['listener1', 'listener2', 'listener1', 'listener2']);
log.clear();
});
testWidgets('Merging change notifiers ignores null', (WidgetTester tester) async {
final TestNotifier source1 = new TestNotifier();
final TestNotifier source2 = new TestNotifier();
final List<String> log = <String>[];
final Listenable merged = new Listenable.merge(<Listenable>[null, source1, null, source2, null]);
final VoidCallback listener = () { log.add('listener'); };
merged.addListener(listener);
source1.notify();
source2.notify();
expect(log, <String>['listener', 'listener']);
log.clear();
}); });
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment