PerformanceHard40 XP5 min read
How do you detect and fix memory leaks in Flutter?
TL;DR: Common leaks: not canceling StreamSubscriptions, not disposing AnimationControllers/TextEditingControllers, static references to BuildContext, and closures that capture large objects. Use Flutter DevTools Memory tab to track allocations and find what's retaining objects.
Full Answer
Most Common Flutter Memory Leaks
- ▸StreamSubscription not canceled in dispose() — keeps stream alive and holds listener reference
- ▸AnimationController/TextEditingController not disposed — leaks vsync and ChangeNotifier listeners
- ▸Timer not canceled — fires after widget is unmounted, may setState on dead widget
- ▸Static references to BuildContext or State — prevents GC of the entire widget subtree
- ▸ChangeNotifier addListener without removeListener — listener count grows unboundedly
🎯
Flutter DevTools Memory tab: take a heap snapshot before and after navigating. Objects whose count keeps growing are likely leaking. Filter by your class name to find the culprit.
Code Examples
dartProper resource disposal pattern
Output
// Each dispose() call severs a reference chain // Without dispose: GC can't collect the widget subtree // Timer without cancel: fires on disposed widget → setState error
Common Mistakes
- ✗Calling setState in a Timer callback without checking mounted — throws 'setState called after dispose'
- ✗Forgetting StreamSubscription.cancel() — the most common leak in reactive Flutter apps
Interview Tip
💡
The golden rule: every resource you allocate in initState() must be released in dispose(). Make a dispose checklist in code review. DevTools Memory 'Allocation tracking' shows which code path is creating the leaking objects.
#memory-leak#dispose#StreamSubscription#DevTools