diff --git a/packages/flutter/lib/src/foundation/change_notifier.dart b/packages/flutter/lib/src/foundation/change_notifier.dart index 566dada9995..13a2e6d0eca 100644 --- a/packages/flutter/lib/src/foundation/change_notifier.dart +++ b/packages/flutter/lib/src/foundation/change_notifier.dart @@ -99,7 +99,7 @@ abstract class ValueListenable extends Listenable { /// See also: /// /// * [ValueNotifier], which is a [ChangeNotifier] that wraps a single value. -class ChangeNotifier extends Listenable { +class ChangeNotifier implements Listenable { ObserverList _listeners = ObserverList(); bool _debugAssertNotDisposed() { diff --git a/packages/flutter/test/foundation/change_notifier_test.dart b/packages/flutter/test/foundation/change_notifier_test.dart index 85c2194eca8..7897c41dc11 100644 --- a/packages/flutter/test/foundation/change_notifier_test.dart +++ b/packages/flutter/test/foundation/change_notifier_test.dart @@ -11,6 +11,24 @@ class TestNotifier extends ChangeNotifier { } } +class HasListenersTester extends ValueNotifier { + HasListenersTester(T value) : super(value); + bool get testHasListeners => hasListeners; +} + +class A { + bool result = false; + void test() { result = true; } +} + +class B extends A with ChangeNotifier { + @override + void test() { + notifyListeners(); + super.test(); + } +} + void main() { testWidgets('ChangeNotifier', (WidgetTester tester) async { final List log = []; @@ -258,9 +276,18 @@ void main() { notifier.removeListener(test2); expect(notifier.testHasListeners, isFalse); }); -} -class HasListenersTester extends ValueNotifier { - HasListenersTester(T value) : super(value); - bool get testHasListeners => hasListeners; + test('ChangeNotifier as a mixin', () { + // We document that this is a valid way to use this class. + final B b = B(); + int notifications = 0; + b.addListener(() { + notifications += 1; + }); + expect(b.result, isFalse); + expect(notifications, 0); + b.test(); + expect(b.result, isTrue); + expect(notifications, 1); + }); }