Chapter 2 · Practice 1 of 5
Keep build() free of costly and repeated work
Why it matters
The Flutter docs say to avoid repetitive and costly work in build() methods, since build() can be called frequently when ancestor widgets rebuild. A parent animation, a theme change or a keyboard opening can all trigger it.
Things that do not belong in build():
- network requests, file reads and database queries,
- parsing JSON or sorting large lists,
- creating controllers, streams or futures that should live as long as the widget.
Compute data in your view model or repository, and hand build() a ready-to-render value. A FutureBuilder whose future is created inside build() is a classic bug: every rebuild starts a new request.
Do
- Create futures and streams in
initState()or a view model, then pass them in - Pre-compute sorted or filtered lists outside
build()
Avoid
- Calling
http.getorjsonDecodeinsidebuild()
Example
// Bad: a new request on every rebuild
Widget build(BuildContext context) {
return FutureBuilder(future: api.fetchOrders(), builder: _render);
}
// Good: the future is created once
late final Future<List<Order>> _orders = api.fetchOrders();
Widget build(BuildContext context) {
return FutureBuilder(future: _orders, builder: _render);
}