IntermediateFlutter Fundamentals

Explain the widget lifecycle in Flutter.

Short Answer

A StatefulWidget's State goes through createState → initState → didChangeDependencies → build (repeated) → didUpdateWidget (on parent rebuild) → deactivate → dispose.

createState() is called once when the framework first creates the State object. initState() runs once, right after, and is where you set up controllers, subscriptions, or one-time initialization — note that BuildContext and inherited widgets aren't fully available yet, so don't use them here for anything that depends on InheritedWidget data.

didChangeDependencies() runs after initState() and again whenever an InheritedWidget the State depends on changes. build() is called every time the framework needs to re-render — it can run many times and must be fast and side-effect-free. If the parent rebuilds with a new widget instance for the same State, didUpdateWidget(oldWidget) runs so you can react to changed configuration. Finally, deactivate() runs when the State is removed from the tree (it may be reinserted elsewhere, e.g. with GlobalKey), and dispose() runs when it's permanently removed — this is where you cancel subscriptions and dispose controllers.

Common Mistakes

  • ×Doing expensive work inside build() instead of initState() or a memoized value.
  • ×Forgetting to dispose() AnimationControllers, StreamSubscriptions, or TextEditingControllers, causing memory leaks.

Interview Tips

  • Naming the exact order (initState → didChangeDependencies → build → didUpdateWidget → dispose) signals real hands-on experience, not just memorized definitions.