Skip to content

Commit 3a3a0db

Browse files
authored
Disallow dispose during listener callback (#114530)
* Disallow dispose during listener callback * addressing comment * add comments to code * Addressing comments * fix test
1 parent 7fd3bb2 commit 3a3a0db

File tree

2 files changed

+22
-0
lines changed

2 files changed

+22
-0
lines changed

packages/flutter/lib/src/foundation/change_notifier.dart

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -321,6 +321,12 @@ class ChangeNotifier implements Listenable {
321321
@mustCallSuper
322322
void dispose() {
323323
assert(ChangeNotifier.debugAssertNotDisposed(this));
324+
assert(
325+
_notificationCallStackDepth == 0,
326+
'The "dispose()" method on $this was called during the call to '
327+
'"notifyListeners()". This is likely to cause errors since it modifies '
328+
'the list of listeners while the list is being used.',
329+
);
324330
assert(() {
325331
_debugDisposed = true;
326332
return true;

packages/flutter/test/foundation/change_notifier_test.dart

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,22 @@ class Counter with ChangeNotifier {
4949
}
5050

5151
void main() {
52+
testWidgets('ChangeNotifier can not dispose in callback', (WidgetTester tester) async {
53+
final TestNotifier test = TestNotifier();
54+
bool callbackDidFinish = false;
55+
void foo() {
56+
test.dispose();
57+
callbackDidFinish = true;
58+
}
59+
60+
test.addListener(foo);
61+
test.notify();
62+
final AssertionError error = tester.takeException() as AssertionError;
63+
expect(error.toString().contains('dispose()'), isTrue);
64+
// Make sure it crashes during dispose call.
65+
expect(callbackDidFinish, isFalse);
66+
});
67+
5268
testWidgets('ChangeNotifier', (WidgetTester tester) async {
5369
final List<String> log = <String>[];
5470
void listener() {

0 commit comments

Comments
 (0)