Performance
Prerequisites: Isolates and concurrency, Stateful widgets and user input
The first rule of performance work: measure before you change anything. Flutter apps are fast by default; most slowdowns come from a few specific mistakes.
Measure with DevTools
Dart DevTools (opened from VS Code or Android Studio) shows:
- The Performance view — frame times. Each frame must be built and drawn in about 16ms for 60 frames per second; slow frames appear red ("jank").
- The CPU profiler — which functions use the most time.
- The Memory view — allocations and leaks.
- Rebuild tracking — which widgets rebuild, and how often.
Always profile in profile mode (flutter run --profile) on a real
device. Debug mode is much slower and not representative.
Common Flutter wins
- Use
constwidgets. Aconstwidget is created once and skipped during rebuilds. - Rebuild less. Split large
buildmethods into smaller widgets, and listen to state as low in the tree as possible, so a change rebuilds only the widgets that depend on it. - Lazy lists. Use
ListView.builderfor long lists, never aColumnwith hundreds of children. - Keep
buildcheap. No sorting, filtering, or parsing inbuild— compute in the model and cache the result. - Move heavy work off the UI isolate with
Isolate.runorcompute. - Size images correctly. Decoding a 4000-pixel photo to show it at
100 pixels wastes memory and time; use
cacheWidth/cacheHeight.
Measuring Dart code
void main() {
final stopwatch = Stopwatch()..start();
final squares = List.generate(1000000, (i) => i * i);
stopwatch.stop();
print('Built ${squares.length} values in under a second: ${stopwatch.elapsed.inSeconds < 1}');
}
Built 1000000 values in under a second: true
For reliable micro-benchmarks, the benchmark_harness package handles
warm-up and repetition — the first runs of any code under the JIT are
slower.
Release builds
flutter build and dart compile exe produce AOT-compiled native
code, which is much faster to start and run than debug builds. Release
builds also tree-shake unused code and icons, reducing app size —
check what takes up space with flutter build apk --analyze-size.
Common mistakes
- Judging performance from a debug build.
- Calling
setStatehigh in the tree for a small change, rebuilding a whole screen instead of one widget.