Keentune
Flutter, oriented
9 chapters
·
about 18 min read
·
free
Flutter does not wrap the platform's buttons and switches. It paints its own, down to the last pixel, from one codebase — there is a Dart implementation of the iOS switch and a separate one of the Android switch. That decision sets the framework's shape. With no native view to hold anything for you, Flutter keeps three parallel trees: widgets describe, elements remember, render objects measure and paint. Almost every "why did it do that" — a lost scroll position, a widget that ignores its own width, a rebuild nobody asked for — is answered at one of those three layers. This guide is about which.
Each chapter opens with the short version. Tap one to read the detail.
Three trees: describe, remember, paint
~2 min
A widget is an immutable description that Flutter discards and rebuilds, potentially every frame. What persists is its element — one per widget, holding identity and State — and beneath that a render object does layout and painting. Building widgets is cheap because they are configuration, not the thing on screen.
What survives a rebuild — State, and the keys that decide
~3 min
createState runs once per mounted element and its State outlives every widget instance after it. Whether that element is reused at all comes down to one comparison: same runtime type *and* equal key. With no key, type alone decides — so reordering stateful siblings silently leaves each State attached to the wrong item.
BuildContext is a position, and it is how shared data reaches down
~2 min
A BuildContext is a handle to one element's location in the tree, not a global object. Every lookup spelled X.of(context) walks *upward* from that position — and the context inside a build method sits above everything that method returns, which is the classic "no Scaffold found" failure.
Constraints go down, sizes go up — and the errors when they don't
~3 min
Layout is one downward pass of constraints and one upward pass of sizes, with the parent placing the child. A widget cannot choose any size it likes and never knows its own position — which is why width: 100 so often yields something that is not 100 wide, and why most Flutter errors are really a missing constraint.
One isolate, one event loop, one frame budget
~2 min
Your app runs on a single isolate with a single event loop, and painting a frame is just another event in that queue. So await buys nothing against a slow computation: it releases the loop while *waiting*, but synchronous work longer than the frame gap stalls everything, the next frame included.
What happens sixty times a second
~2 min
An AnimationController emits a new value every time the hardware wants a frame, so an animation turns your rebuild scope into a per-frame cost. Keeping the unchanging part of a subtree out of that loop — through a builder's child argument or a const instance — is most of animation performance.
A stack you push, or state you declare
~2 min
Navigator keeps a stack of routes, and push returns a future that completes with whatever pop passes back. Named routes look like the tidy option and are no longer recommended: their deep-link behaviour cannot be customised and browser forward is unsupported.
Touches are negotiated, not claimed
~2 min
Pointer events hit-test to the innermost widget and then bubble to the root, with no way to stop them. Above that, recognisers competing for the same touch negotiate: exactly one wins, or none does. That negotiation, not your callback, is usually why a tap "does nothing".
Three environments, each misleading in its own way
~3 min
Your code runs in three places that behave differently: a widget test whose clock only moves when you pump it, a debug build that is quick to iterate on and useless to measure, and a release build with the assertions and tooling stripped out. Knowing which one you are in is most of the debugging.
See the full Flutter curriculum
Written by Keentune. We are not affiliated with or endorsed by the organizations whose documentation informs this guide, and any linked sources belong to their respective owners.
All exam, test, and product names and trademarks are the property of their respective owners and are used here for identification and reference only. Keentune is independent study practice — not affiliated with, authorized, or endorsed by any of these organizations.
© 2026 SportaApp LLC