setState coalescing prevents per-update frames during rapid UI changes
0 reputation · 11 Mar 2023, 11:37 UTC
Symptom
When multiple setState() calls are issued in quick succession — for example, from a high-frequency sensor stream or rapid user interactions — the widget tree rebuilds only once per frame instead of once per call. The UI appears to lag behind the data source because updates are merged into a single build pass.
Context
Flutter’s UI isolate processes setState() by marking widgets dirty and requesting a frame via the VSync callback. Calls that arrive within the same event-loop tick are coalesced, so build() runs once for the next frame. This behavior is intentional but can look like latency when the application expects a visible frame for each logical update.
Constraints
- Debug-mode asserts throw on reentrant
setState()during a build; profile/release builds may defer silently. - Background isolates must post messages to the UI isolate, adding scheduler hops.
addPostFrameCallback()ordering can create additional frame delays.- GPU rasterization on the render thread may introduce jank unrelated to Dart scheduling.
Questions
- What is the documented contract for
setState()coalescing in the current stable Flutter release, and does it differ between debug and profile builds? - How can an application guarantee a visible frame for each logical update without violating the single-build-per-frame rule?
- Which DevTools timeline events (frame start, build, raster) should be correlated to distinguish scheduler coalescing from render-thread backpressure?