D
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