Widget tree: Stateless and Stateful
In Flutter everything is a widget: a button, a padding, an entire screen. Widgets form a tree, and each one is an immutable configuration — the widget object itself never changes; a new one is created instead.
There are two core kinds:
- StatelessWidget — has no internal state; the same input always produces the same output
- StatefulWidget — has changing state, which lives in a separate
Stateobject
The reason for that split: the widget is recreated on every rebuild, but the State object survives. That is why a TextEditingController, an animation controller and so on live in the State, not in the widget.
Flutter actually keeps three trees, and the distinction comes up in interviews:
- Widget tree — the configuration you write; cheap, recreated often
- Element tree — the "live" instances of those widgets; holds state and position in the tree
- Render tree — the layer that measures and paints
On rebuild Flutter compares the new widget tree with the old one and applies only the difference to the element and render trees. That is why build() being called often is not a problem in itself — doing heavy work inside build() is.
| Question | StatelessWidget | StatefulWidget |
|---|---|---|
| Internal mutable state | none | yes, in a `State` object |
| When it rebuilds | when the parent rebuilds it | also when `setState` is called |
| Typical use | an icon, a label, a static card | a form, a counter, an animation |
| Resources and dispose | not needed | must be cleaned up in `dispose()` |
Interview tip. Only defining the two is a junior answer. A strong one adds the why: widgets are immutable, so mutable state lives in a separate State object that survives rebuilds. Finish with the practical consequence: "which is why I create controllers in `State` and close them in `dispose()`". If you want to go one step further, mention the three trees — most candidates do not know them.
📚 Sources and documentation
- Introduction to widgetsofficialdocs.flutter.dev
- StatefulWidget classofficialapi.flutter.dev
The "Performance considerations" section documents rebuild cost directly.
- StatelessWidget classofficialapi.flutter.dev
- Element classofficialapi.flutter.dev