Sparround

Optimising rebuilds

Performance conversations in Flutter almost always revolve around rebuilds. The nuance that matters: calling build() is cheap in itself — the problem is what gets rebuilt.

The main tools:

  • `const` constructors — a const widget is canonicalised and is not rebuilt at all. The cheapest optimisation there is
  • Narrowing the rebuild area — extracting the changing part into its own widget and keeping setState as low in the tree as possible
  • `RepaintBoundary` — isolating a frequently changing region into its own layer (animations, video)
  • Keys — correct element matching when list items move around

Keys are the most misunderstood topic here. On rebuild Flutter matches old and new widgets by type and position. When a list item is removed or reordered, positional matching produces the wrong result — state such as a checkbox selection "sticks" to the wrong item.

Giving ValueKey(item.id) makes Flutter match by identity, and the problem disappears.

The rule: if you have a list of same-typed StatefulWidgets whose order can change, add keys. A static list that never reorders does not need them.

Interview tip. The sentence that matters most here: measure first, optimise second. Most candidates immediately list const and RepaintBoundary; a strong answer starts by finding which frame blew the budget, using the DevTools performance overlay and timeline. The frame budget for 60 fps is about 16 ms, and jank is exceeding it.

📚 Sources and documentation