Allow ChangeNotifier to be mixed in again (#23631)
Luckily this class didn't actually need to extend its superclass, it
only implements the interface. So we can change `extends` to
`implements` and that's close enough, while allowing the class to be
mixed in again.
diff --git a/packages/flutter/lib/src/foundation/change_notifier.dart b/packages/flutter/lib/src/foundation/change_notifier.dart
index 566dada..13a2e6d 100644
--- a/packages/flutter/lib/src/foundation/change_notifier.dart
+++ b/packages/flutter/lib/src/foundation/change_notifier.dart
@@ -99,7 +99,7 @@
/// See also:
///
/// * [ValueNotifier], which is a [ChangeNotifier] that wraps a single value.
-class ChangeNotifier extends Listenable {
+class ChangeNotifier implements Listenable {
ObserverList<VoidCallback> _listeners = ObserverList<VoidCallback>();
bool _debugAssertNotDisposed() {
diff --git a/packages/flutter/test/foundation/change_notifier_test.dart b/packages/flutter/test/foundation/change_notifier_test.dart
index 85c2194..7897c41 100644
--- a/packages/flutter/test/foundation/change_notifier_test.dart
+++ b/packages/flutter/test/foundation/change_notifier_test.dart
@@ -11,6 +11,24 @@
}
}
+class HasListenersTester<T> extends ValueNotifier<T> {
+ 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<String> log = <String>[];
@@ -258,9 +276,18 @@
notifier.removeListener(test2);
expect(notifier.testHasListeners, isFalse);
});
-}
-class HasListenersTester<T> extends ValueNotifier<T> {
- 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);
+ });
}