How does Flutter manage memory, and how do you avoid leaks?
Short Answer
Dart uses automatic garbage collection, so you don't free memory manually — leaks in Flutter almost always come from long-lived objects (controllers, streams, listeners) holding references that prevent disposed widgets' resources from being collected.
The Dart VM's generational garbage collector reclaims objects with no remaining references, so typical "manual memory management" bugs (like double-free) don't apply. What does cause real leaks in Flutter apps is forgetting to release long-lived resources tied to a widget's lifetime: an `AnimationController`, `TextEditingController`, `ScrollController`, or `StreamSubscription` started in `initState()` but never released in `dispose()` keeps running (and keeps its callbacks alive) even after the widget is gone.
A second common source is global/static state (singletons, global event buses) holding a reference to a callback or object tied to a specific screen — the screen is popped, but the global reference keeps it (and everything it references) alive. Use Flutter DevTools' memory view to take heap snapshots and look for unexpectedly retained widget/controller instances after navigating away.
Common Mistakes
- ×Subscribing to a Stream or animation in `initState()` without a matching `cancel()`/`dispose()`.
- ×Registering a callback on a global singleton from a screen, then never unregistering it when the screen closes.
Interview Tips
- →Mention Flutter DevTools' memory snapshot/diff tooling specifically — it shows you've actually debugged a leak, not just read about the concept.
Related Questions
Explain the widget lifecycle in Flutter.
A StatefulWidget's State goes through createState → initState → didChangeDependencies → build (repeated) → didUpdateWidget (on parent rebuild) → deactivate → dispose.
What are isolates in Dart and when do you need them?
An isolate is Dart's unit of concurrency — a separate memory heap and event loop running independently, with no shared mutable state — used to run CPU-heavy work in parallel without blocking the UI thread.