setState after the widget being disposed
mhbdev opened this issue · 0 comments
mhbdev commented
Steps to reproduce:
- Create a basic flutter application
- Create a StatefulWidget and use this snippet inside a Scaffold body
return Scaffold(
body: SafeArea(
child: Stack(
children: [
Positioned.fill(
child: FloatingBubbles(
noOfBubbles: 25,
colorsOfBubbles: const [
Colors.orange,
Colors.red,
Colors.blue,
],
sizeFactor: 0.16,
duration: 5, // in seconds
opacity: 10,
paintingStyle: PaintingStyle.fill,
strokeWidth: 8,
speed: BubbleSpeed.slow, // normal is the default
),
),
Center(
child: Text('Hello World!')
),
],
),
),
);
- before the
duration
you passed to FloatingBubbles widget navigate to another page.
void initState() {
Future.delayed(Duration(seconds: 2)).then((_) => Navigator.pushReplacement(context, MaterialPageRoute(builder: (context) => const Scaffold(body: Placeholder(),),)));
super.initState();
}
- After completing the duration of FloatingBubbles widget you can see this error log.
══╡ EXCEPTION CAUGHT BY FLUTTER FRAMEWORK ╞═════════════════════════════════════════════════════════
The following assertion was thrown:
setState() called after dispose(): _FloatingBubblesState#7a888(lifecycle state: defunct, not
mounted)
This error happens if you call setState() on a State object for a widget that no longer appears in
the widget tree (e.g., whose parent widget no longer includes the widget in its build). This error
can occur when code calls setState() from a timer or an animation callback.
The preferred solution is to cancel the timer or stop listening to the animation in the dispose()
callback. Another solution is to check the "mounted" property of this object before calling
setState() to ensure the object is still in the tree.
This error might indicate a memory leak if setState() is being called because another object is
retaining a reference to this State object after it has been removed from the tree. To avoid memory
leaks, consider breaking the reference to this object during dispose().
When the exception was thrown, this was the stack:
C:/b/s/w/ir/cache/builder/src/out/host_debug/dart-sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/errors.dart 266:49 throw_
packages/flutter/src/widgets/framework.dart 1097:9 <fn>
packages/flutter/src/widgets/framework.dart 1131:14 setState
packages/floating_bubbles/src/bubbles.dart 142:11 <fn>
C:/b/s/w/ir/cache/builder/src/out/host_debug/dart-sdk/lib/async/zone.dart 1390:47 _rootRun
C:/b/s/w/ir/cache/builder/src/out/host_debug/dart-sdk/lib/async/zone.dart 1300:19 run
C:/b/s/w/ir/cache/builder/src/out/host_debug/dart-sdk/lib/async/zone.dart 1208:7 runGuarded
C:/b/s/w/ir/cache/builder/src/out/host_debug/dart-sdk/lib/async/zone.dart 1248:23 <fn>
C:/b/s/w/ir/cache/builder/src/out/host_debug/dart-sdk/lib/async/zone.dart 1398:13 _rootRun
C:/b/s/w/ir/cache/builder/src/out/host_debug/dart-sdk/lib/async/zone.dart 1300:19 run
C:/b/s/w/ir/cache/builder/src/out/host_debug/dart-sdk/lib/async/zone.dart 1232:23 <fn>
C:/b/s/w/ir/cache/builder/src/out/host_debug/dart-sdk/lib/_internal/js_dev_runtime/private/isolate_helper.dart 48:19 internalCallback
════════════════════════════════════════════════════════════════════════════════════════════════════
It is happening because inside the widget after finishing the Timer, setState is being called but unfortunately in this example, the state is gone and we cannot call setState.