diff --git a/packages/flutter/lib/src/foundation/change_notifier.dart b/packages/flutter/lib/src/foundation/change_notifier.dart index bfd5ce5831..c09c025e09 100644 --- a/packages/flutter/lib/src/foundation/change_notifier.dart +++ b/packages/flutter/lib/src/foundation/change_notifier.dart @@ -321,6 +321,12 @@ class ChangeNotifier implements Listenable { @mustCallSuper void dispose() { assert(ChangeNotifier.debugAssertNotDisposed(this)); + assert( + _notificationCallStackDepth == 0, + 'The "dispose()" method on $this was called during the call to ' + '"notifyListeners()". This is likely to cause errors since it modifies ' + 'the list of listeners while the list is being used.', + ); assert(() { _debugDisposed = true; return true; diff --git a/packages/flutter/test/foundation/change_notifier_test.dart b/packages/flutter/test/foundation/change_notifier_test.dart index 8ff4e29a89..9025eada78 100644 --- a/packages/flutter/test/foundation/change_notifier_test.dart +++ b/packages/flutter/test/foundation/change_notifier_test.dart @@ -49,6 +49,22 @@ class Counter with ChangeNotifier { } void main() { + testWidgets('ChangeNotifier can not dispose in callback', (WidgetTester tester) async { + final TestNotifier test = TestNotifier(); + bool callbackDidFinish = false; + void foo() { + test.dispose(); + callbackDidFinish = true; + } + + test.addListener(foo); + test.notify(); + final AssertionError error = tester.takeException() as AssertionError; + expect(error.toString().contains('dispose()'), isTrue); + // Make sure it crashes during dispose call. + expect(callbackDidFinish, isFalse); + }); + testWidgets('ChangeNotifier', (WidgetTester tester) async { final List log = []; void listener() {