Flutter
The framework itself: widgets, rendering, layout, navigation, platform interop, testing and release. Interviewers start here because Flutter drawing every pixel itself explains most of its behaviour.
on this pageshowhide
guide
overview
~2 minFlutter is Google's UI toolkit for building Android, iOS, web and desktop apps from one Dart codebase. Its defining choice is that it draws every pixel itself: instead of wrapping the platform's buttons and lists, it lays out and paints its own widgets onto a surface its engine controls. Interviewers start there because that one decision explains most of what follows: why an app can look the same on every device, why the cost of each frame is Flutter's to manage, and why anything the platform owns, such as a camera, payments or a native map, has to be reached across a boundary. A good Flutter answer says which tree or which thread a behaviour lives in, and what it costs. The hub splits into the framework core, the surfaces built on it, the app around them and the road to users. The core is [widget kinds and lifecycle](/topics/mob-flutter-widget-tree), the [box layout model](/topics/mob-flutter-layout-constraints), [built-in reactivity](/topics/mob-flutter-state-management) and, beneath all three, the [engine and frame pipeline](/topics/mob-flutter-rendering). On that core sit the everyday surfaces: [navigation and routing](/topics/mob-flutter-navigation), [scrollable views](/topics/mob-flutter-scrolling), [visual design kits](/topics/mob-flutter-ui-kits), [bundled resources](/topics/mob-flutter-assets), the [animation system](/topics/mob-flutter-animations), [gestures and focus](/topics/mob-flutter-input) and [accessibility and locales](/topics/mob-flutter-inclusive). App-level concerns follow: [codebase layering](/topics/mob-flutter-architecture), [backend API calls](/topics/mob-flutter-networking), [on-device persistence](/topics/mob-flutter-storage), the [FlutterFire plugins](/topics/mob-flutter-firebase), and [native interop](/topics/mob-flutter-platform-interop) for everything Flutter does not wrap. The last group is quality and delivery: the [dev loop and DevTools](/topics/mob-flutter-devtools), [jank and size tuning](/topics/mob-flutter-perf), [automated verification](/topics/mob-flutter-testing), [shipping to stores](/topics/mob-flutter-release) and [web and desktop targets](/topics/mob-flutter-multiplatform). Junior rounds check fluency: stateless against stateful, how a `Row` shares out its width, how to open a screen and get a value back. Middle rounds move to lost state, rebuild scope, async builders and routing that survives a deep link. Senior and principal rounds turn into diagnosis and design: why a frame dropped and on which thread, where an app's testable seams sit, what crossing to native code costs, and when Flutter is the wrong choice for a product. Learn how widgets, elements and `State` relate first, then the layout rule, then `setState` and where it stops being enough. Rendering and performance make sense only after those three; the app-level sections can be taken in almost any order once they are solid.
primer
### Widgets are descriptions, and they are cheap A widget is an immutable description of part of the UI, not the thing on screen. `build` returns a fresh set of descriptions whenever something changes, and the framework compares them with what it already holds. That is why rebuilding is the normal way to update a screen rather than a last resort, and why an answer that tries to "change a widget in place" has the model backwards. ### State lives in elements, not in widgets The long-lived objects are **elements**, which hold a widget's place in the tree, and the **State** objects attached to stateful ones. Because widgets are replaced on every rebuild, anything that must survive, such as a counter, a controller or a scroll offset, belongs in a `State` or higher up. Whether that `State` is kept or discarded depends on the widget's type and **key** at that position, which is where most "my state disappeared" bugs start. ### Layout follows strict rules, in one pass Parents hand children constraints, children pick a size within those bounds, and parents decide where they go. A child cannot pick its own position, and ordinary layout does not negotiate over several rounds; widgets that measure children speculatively exist and are priced accordingly. Nearly every overflow stripe and unbounded-size error is this rule meeting a widget that wanted more space than it was offered, or an unlimited amount, so reading the constraints at the failing spot is the first move in any layout question. ### The framework draws; the platform hosts Flutter paints through its own engine and renderer rather than creating native controls. That buys consistent rendering across devices and full control of each frame. It also costs a boundary: platform features arrive through channels, FFI or plugins, embedded native views are comparatively expensive, and accessibility, text input and platform look are bridged or recreated by the framework rather than inherited from native widgets. ### Two threads decide a frame Your Dart code, including build and layout, runs on the main isolate's UI thread; the engine rasterizes the result on a separate raster thread. Jank is a frame that missed its deadline on one of them, and naming which one is half of a performance answer. Dart's `async` interleaves work on a single isolate rather than running it in parallel, so CPU-heavy work needs another isolate. ### Reactivity scales in steps `setState` is scoped to one `State`. Listenables, inherited widgets and async builders carry changes further through the tree without any package. Past that, teams adopt a state library, and interviewers want the reason for the step, such as scope, testability or async handling, not a favourite package name. ### The build mode changes what you measure On mobile, debug builds JIT-compile Dart to support hot reload and run extra checks, while profile and release builds are compiled ahead of time to native code. Speed, startup and even some bugs differ between them, so where you measured is part of every performance claim you make.
- Widget
- An immutable description of part of the UI: configuration, not the object on screen. Rebuilt freely, while the framework decides what actually changes.
- Element
- The long-lived instance of a widget at one position in the tree. It holds its children, a stateful widget's State, and links widgets to render objects.
- RenderObject
- The object that performs layout, painting and hit testing for part of the UI. Only some widgets create one; most just compose other widgets.
- State
- The mutable, long-lived companion of a StatefulWidget, kept by its element across rebuilds and disposed when that element leaves the tree for good.
- BuildContext
- A handle to a widget's element, used to look up ancestors such as the theme, the navigator or inherited data from that position in the tree.
- InheritedWidget
- A widget that exposes data to its descendants and rebuilds the ones that read it through their BuildContext whenever that data changes.
- Key
- An identity attached to a widget so the framework can match it with the right element and State when siblings are reordered, inserted or removed.
- BoxConstraints
- The minimum and maximum width and height a parent passes to a child during layout; the child's chosen size must fall inside them.
- setState
- The State method that applies a change and marks its element to rebuild on the next frame.
- Sliver
- A piece of a scrollable area that lays itself out against the viewport, so lazy lists, grids and headers can share one scroll view.
- Isolate
- Dart's unit of concurrency, with its own memory and event loop, communicating by messages. The UI runs on the main isolate; heavy CPU work moves elsewhere.
- Platform channel
- A named, asynchronous message pipe between Dart and host-platform code, carrying encoded method calls, results and event streams.
- Plugin
- A package that ships host-platform code beside its Dart API, registered by the Flutter tool when the app is built.
- Impeller
- Flutter's current rendering runtime on iOS and Android, designed to avoid first-use shader compilation stalls by preparing its pipelines ahead of time.
- Hot reload
- Injecting changed Dart code into a running debug app and rebuilding widgets while keeping their state. Native code changes need a full rebuild.
- Build mode
- Debug, profile or release: how the app is compiled and which checks it runs. Only profile and release builds reflect real performance.
- Jank
- A visible stutter caused by a frame that missed its display deadline, on either the UI thread or the raster thread.
- Golden test
- A test that renders a widget to an image and compares it with an approved reference image, failing when the pixels differ.
- Flavor
- A named build variant, usually one per environment, with its own application id, configuration and often its own signing.
Follow one tap to the next frame. The engine receives the touch from the host platform and hands it to the framework, which hit-tests the render tree and lets competing gesture recognizers settle who owns it. The winning handler changes some state, through `setState`, a notifier or a stream event, which flags elements for rebuild and asks the engine for a new frame. On that frame the framework rebuilds only the dirty elements, updates the render objects whose properties changed, lays out what may have moved and repaints what was marked. The resulting layer tree goes to the raster thread, where the renderer turns it into GPU work. The rest of the hub attaches to that loop rather than sitting beside it: - **Navigation, theming, localization and scrolling** are widgets too: the navigator is a stateful widget holding a stack of routes, a theme is inherited data, and a scroll view is a viewport that builds children as they come into view. - **Animations** are state that changes on every frame, driven by a ticker, so they cost a rebuild or a repaint per frame unless their scope is kept small. - **Networking, storage and Firebase** live outside the tree in plain Dart objects, the repositories and services of the layered architecture, and reach the UI through the same reactive tools as any other state. - **Native interop** leaves the loop: channels cross to host code asynchronously, FFI calls C directly, platform views embed native UI in the frame, and plugins package all of it for reuse. - **DevTools, tests and release builds** observe or package the same loop: the inspector shows the trees, widget tests drive frames on a fake binding, and the build mode decides how the Dart runs. Three of those ideas meet in one small `State`: data held across rebuilds, a dependency registered through the context, and a subtree the rebuild skips. ```dart class _TallyState extends State<Tally> { int taps = 0; // survives rebuilds: the element keeps this State @override Widget build(BuildContext context) { final scheme = Theme.of(context).colorScheme; // theme change -> rebuild return GestureDetector( onTap: () => setState(() => taps++), // dirty now, rebuilt next frame child: Column(children: [ const Legend(), // identical instance: its subtree is skipped Text('$taps', style: TextStyle(color: scheme.primary)), ]), ); } } ``` Rebuilding the whole `Column` is not the cost it looks like: only the text actually changes, the legend is reused untouched, and a theme switch would rebuild this `State` through the lookup even though nobody called `setState`.
- Widget Kinds & Lifecycle →
Widgets, elements and State: what is rebuilt, what survives, and why keys and BuildContext matter before anything else.
- Box Layout Model →
The constraint rule behind every Row, Column and overflow error, which every screen you build or debug depends on.
- Built-In Reactivity →
How changes reach the screen without a package, and the point where setState and listenables stop being enough.
- Navigation & Routing →
Moving between screens, from push and pop to URL-driven routing, redirects and deep links.
- Engine & Frame Pipeline →
The trees and frame pipeline beneath the widgets, needed to reason about what a rebuild or repaint really costs.
- Jank & Size Tuning →
Finding a dropped frame, on which thread, and fixing it; this builds on everything above.
Creating a future inside
buildand handing it to a builder, so every rebuild starts a new request; see this question.Judging jank or startup time in a debug build, whose JIT code and extra checks distort timings; measure in profile mode on a physical device.
Saying
setStateredraws the whole screen: it marks one element dirty, and only changed render properties lead to new layout or paint.Putting a
ListViewstraight inside aColumnand patching the error with arbitrary sizes instead of finding which constraint was unbounded.Reordering or removing stateful siblings without keys, then blaming the framework when a checkbox or typed text stays attached to the wrong row.
Creating an
AnimationController,ScrollController,TextEditingControllerorFocusNodeinsidebuild, or never disposing one, which leaks resources and drops focus.Calling
Scaffold.ofor a provider lookup with a context that sits above the widget being looked up, usually the context of the widget that creates it.Treating
asyncas parallel: awaiting I/O keeps the UI responsive, but heavy parsing or image work on the main isolate still drops frames.Describing Flutter as a wrapper around native widgets, or platform channels as synchronous calls; both misstate the boundary the interviewer is probing.
Keeping tokens or other secrets in
shared_preferences, which is plain app storage; Secure Storage exists for exactly that.
This guide assumes Flutter 3.47 on Dart 3, the release the questions below describe. Several earlier changes still come up, because many codebases, packages and tutorials predate them: - **Flutter 3.10** shipped with Dart 3, which requires sound null safety and added records, patterns and class modifiers. The same release made Impeller the default renderer on iOS. - **Flutter 3.16** made Material 3 the default for new themes and introduced `TextScaler`, deprecating the single numeric text scale factor. - **Flutter 3.22** made WebAssembly compilation for the web stable. - **Flutter 3.27** made Impeller the default on Android, keeping a fallback for devices that cannot run it. - The HTML web renderer has since been removed, so a web build now draws with CanvasKit or skwasm. When an answer depends on the release, such as which renderer runs, whether Material 3 is on or how text scaling is read, say which one you are describing. An interviewer who maintains an older app may ask about the earlier behaviour on purpose, and naming the era is part of a good answer.
Interviewers expect you to place Flutter among the ways to build a mobile app, not only to use it. Native development, with SwiftUI or UIKit on iOS and Jetpack Compose or Views on Android, gives full platform fidelity and first access to new APIs at the cost of two codebases. React Native also shares one codebase, but it drives the platform's own UI components from JavaScript, so screens look native by default. Kotlin Multiplatform shares business logic in Kotlin while each platform can keep its own UI, and Compose Multiplatform extends that sharing to the UI. Flutter's trade-off is the reverse of native: one rendering engine and one look everywhere, with platform features reached through interop. Around the framework sit the pieces a Flutter team chooses. A state library such as Provider, Riverpod or BLoC arrives once the built-in tools stop scaling; [Choosing a State Library](/topics/mob-flutter-state-management-choosing) compares them. go_router is the common answer for URL-based navigation, dio or http for REST calls, sqflite, Drift or a key-value store for persistence, and Firebase, through the FlutterFire plugins, is the managed backend many Flutter apps start on. A defensible choice names what the app needs rather than what is popular.
explore
- Widget Kinds & Lifecycle26 questions
- Stateless vs Stateful6 questions
- State Object Callbacks5 questions
- BuildContext & Lookup5 questions
- Inherited Data Propagation5 questions
- Keys & Identity5 questions
- Engine & Frame Pipeline25 questions
- Three-Tree Architecture5 questions
- Custom RenderObjects5 questions
- Build, Layout & Paint Passes5 questions
- Impeller Renderer5 questions
- Canvas Painting5 questions
- Box Layout Model26 questions
- Sizing Rules & Overflow5 questions
- Rows, Columns & Flex5 questions
- Overlapping Children5 questions
- Responsive & Adaptive UI6 questions
- Aspect & Fit Widgets5 questions
- Scrollable Views28 questions
- Lazy Lists & Grids5 questions
- Slivers & CustomScrollView5 questions
- Scroll Position & Physics5 questions
- Nested Scrolling5 questions
- Paged & Infinite Lists4 questions
- Reorderable & Animated Lists4 questions
- Visual Design Kits27 questions
- Material 3 Components6 questions
- Themes & Color Schemes5 questions
- Cupertino Components5 questions
- Text & Decoration5 questions
- Text Fields & Validators6 questions
- Bundled Resources21 questions
- Asset Declaration6 questions
- Image Providers & Cache6 questions
- Custom Typefaces5 questions
- Icons & Vector Graphics4 questions
- Built-In Reactivity19 questions
- Ephemeral vs App State4 questions
- Listenables & Notifiers5 questions
- Future & Stream Builders5 questions
- Choosing a State Library5 questions
- Codebase Layering23 questions
- MVVM & Repositories6 questions
- Service Location & Injection6 questions
- Commands & Result Types6 questions
- Feature-First Packaging5 questions
- Navigation & Routing30 questions
- Animation System30 questions
- Implicitly Animated Widgets5 questions
- Controllers & Tickers5 questions
- Tweens & Curves5 questions
- Builders & Transitions5 questions
- Hero Flights5 questions
- Physics-Based Motion5 questions
- Gestures & Focus15 questions
- Tap & Drag Detection6 questions
- Recognizer Arena4 questions
- Keyboard & Shortcuts5 questions
- Accessibility & Locales21 questions
- Semantics Tree5 questions
- Text Scaling & Targets5 questions
- ARB Message Catalogs5 questions
- RTL & Number Formats6 questions
- Backend API Calls26 questions
- REST Clients & Interceptors6 questions
- JSON-Mapped Models6 questions
- Live Socket Connections5 questions
- GraphQL Clients5 questions
- Offline & Retries4 questions
- On-Device Persistence24 questions
- Key-Value Preferences4 questions
- Raw SQLite Access5 questions
- Drift Query Layer5 questions
- Secure Storage5 questions
- Document & Cache Paths5 questions
- FlutterFire Plugins29 questions
- Firebase Project Wiring4 questions
- Firebase Auth Listeners5 questions
- Firestore & Storage Calls5 questions
- FCM Message Handling5 questions
- Remote Config & Callables5 questions
- Analytics & Crashlytics5 questions
- Native Interop36 questions
- Method & Event Channels5 questions
- Pigeon Codegen5 questions
- FFI Bindings5 questions
- Federated Plugins6 questions
- Hosted Platform Views5 questions
- Add-to-App Embedding4 questions
- App States & Permissions6 questions
- Dev Loop & DevTools30 questions
- Hot Reload & Restart5 questions
- Debug, Profile & Release5 questions
- Widget Inspector6 questions
- Heap Snapshots & Leaks5 questions
- Logging & Breakpoints5 questions
- Error Hooks & Reporting4 questions
- Jank & Size Tuning26 questions
- Rebuild Scope4 questions
- Frame Timing Analysis5 questions
- Raster Cost Traps6 questions
- Isolate Offloading6 questions
- Binary Footprint & Startup5 questions
- Automated Verification21 questions
- Widget Tests5 questions
- Golden Image Tests5 questions
- On-Device Integration Tests5 questions
- Mocks & Fakes6 questions
- Shipping to Stores30 questions
- Flavors & Environments5 questions
- Android App Bundles6 questions
- Xcode Archive & Upload5 questions
- Build Numbers & Obfuscation4 questions
- Pipeline Automation4 questions
- App Review Rules6 questions
- Web & Desktop Targets12 questions
- CanvasKit & Skwasm6 questions
- Windows, Mac & Linux6 questions
questions
525 · 21 sectionsIn Flutter, what is a BuildContext, and how does a call like Theme.of(context) use it to find a value?
basics
~10 sA BuildContext is the widget's Element, its handle to one position in the tree. Theme.of(context) finds the nearest Theme above that position and registers a dependency, so the widget rebuilds when that theme changes.
In Flutter, what problem does an InheritedWidget solve, and how do you declare one so descendants can read its data?
basics
~20 sAn InheritedWidget makes a value available to every descendant without passing it through each constructor. You subclass it with final fields, add static of/maybeOf methods that register a dependency, and override updateShouldNotify so only registered dependents rebuild when the value changes.
In Flutter, what is a widget's key for, and when do you actually need to give a widget one?
basics
~20 sA key tells Flutter which old widget a new one replaces: an element is reused only when runtimeType and key match. Same-type stateful siblings that can be inserted, removed or reordered need one, or their state stays with the position.
In Flutter, in what order does the framework call a State object's lifecycle methods, from createState to dispose?
basics
~20 screateState, then the State is mounted, initState runs once, didChangeDependencies follows, then build. Later builds follow setState, didUpdateWidget or a dependency change; on removal deactivate runs, and dispose ends it unless the subtree is reinserted within that frame.
In Flutter, what is the difference between a StatelessWidget and a StatefulWidget, and when do you actually need the stateful one?
basics
~20 sA StatelessWidget builds only from its final fields and inherited data; a StatefulWidget creates a long-lived State object that holds changing values and rebuilds via setState. Choose stateful when the widget itself owns data that changes while it is on screen.
In Flutter, what are the widget, element and render object trees, and what does each one hold?
basics
~20 sWidgets are immutable, short-lived descriptions of UI. Elements are the long-lived instances that hold each widget's position in the tree, its children and any State. Render objects, created by RenderObjectWidgets, hold size and position and do layout, painting and hit testing.
In Flutter, when is CustomPainter.shouldRepaint called, what should it return, and what goes wrong with always true or always false?
basics
~20 sshouldRepaint runs when a new painter instance replaces the old one, typically after a rebuild. Return true only if the new painter would draw something different, by comparing its fields with oldDelegate's. Always true wastes repaints; always false leaves stale drawings.
In a Flutter voice-memo app, how do you repaint a live audio waveform on every new amplitude sample without rebuilding the widget tree?
basics
~10 sKeep the samples in a ChangeNotifier owned by the State and pass it to the painter's super(repaint: ...). Each notifyListeners makes RenderCustomPaint call markNeedsPaint, so only paint runs: no setState, no build, no layout.
In Flutter, what happens between one vsync signal and the next rendered frame, and in what order do the phases run?
basics
~20 sEach frame, SchedulerBinding runs transient callbacks (animation ticks), then their microtasks, then persistent callbacks that rebuild dirty elements, lay out, paint into a layer tree and composite it, then post-frame callbacks. The raster thread draws the resulting scene.
In Flutter, what work runs on the UI thread versus the raster thread, and what changed when the UI and platform threads were merged?
basics
~20 sThe UI thread runs Dart (build, layout, paint) and produces a layer tree; the raster thread renders it through the GPU. Since Flutter 3.29 on iOS and Android, Dart runs on the platform main thread; rasterizing stays separate.
In Flutter, what are the main axis and cross axis of a Row and a Column, and which properties align children along each?
basics
~20 sThe main axis is the direction children are laid out: horizontal for Row, vertical for Column; the cross axis is perpendicular. mainAxisAlignment (default start) and mainAxisSize (default max) act on the main axis, crossAxisAlignment (default center) on the cross axis.
In Flutter, what does the SafeArea widget do, and which of its parameters let you tune the padding it applies?
basics
~20 sSafeArea pads its child by the MediaQuery padding so system UI such as the status bar, notch and home indicator does not cover it. Per-side booleans switch sides off, minimum sets a floor, and maintainBottomViewPadding keeps the bottom inset while the keyboard is open.
In Flutter layout, what does the rule 'constraints go down, sizes go up, parent sets position' mean for a widget?
basics
~20 sEach parent passes BoxConstraints (min and max width and height) down, each child picks a size inside them and reports it up, and the parent then places the child. A widget cannot choose its position or a size outside its constraints.
In Flutter, how does a Stack decide its own size and place its children, and how do positioned and non-positioned children differ?
basics
~20 sA Stack sizes itself to its largest non-positioned child, within its constraints, and aligns those children (default top-start). Positioned children don't affect its size; they are pinned by their insets afterwards, and later children paint on top.
In Flutter, what is the difference between Expanded and Flexible inside a Row or Column, and what does FlexFit change?
basics
~20 sExpanded is Flexible with FlexFit.tight: the child must fill its share of the leftover main-axis space. Flexible defaults to FlexFit.loose: the child may be smaller than its share, and the unused space stays free instead of going to siblings.
In Flutter, how do you scroll a ListView back to the top from a button using a ScrollController?
basics
~20 sCreate a ScrollController in a State, pass it to the ListView's controller parameter, and on tap call animateTo(0, duration:, curve:) or jumpTo(0). Guard with hasClients so nothing runs before the list is attached, and dispose the controller.
In Flutter, what is the difference between a ListView built from a children list and ListView.builder, and when should you use each?
basics
~20 sListView(children: ...) needs every child widget constructed up front, which suits short, fixed lists. ListView.builder calls itemBuilder only for indexes near the viewport, so a 5,000-row list builds just the rows on screen plus a small cache area.
In Flutter, how do you put a horizontal card carousel inside a vertically scrolling page without layout errors?
basics
~20 sGive the horizontal list a fixed height, usually a SizedBox around a horizontal ListView.builder, and place it as one item of the vertical list. Its cross axis is then bounded, it stays lazy, and horizontal and vertical drags do not conflict.
In a Flutter infinite ListView, why can one scroll fire several requests for the same page, and how do you prevent it?
basics
~20 sThe scroll listener fires on every offset change and extentAfter stays under the threshold while the request runs, so each event starts another fetch. Set an in-flight flag synchronously before the first await, and discard responses from before a refresh.
In Flutter, how do a Form, its GlobalKey<FormState> and TextFormField validators work together when the user taps Submit?
basics
~20 sA Form keyed with a GlobalKey<FormState> tracks its TextFormField descendants. On submit, validate() runs every validator (null means valid, a string becomes the error), returns true only if all pass, and save() then calls each onSaved.
In Flutter, what do MaterialApp and Scaffold each provide, and why does Scaffold.of(context) sometimes fail to find the Scaffold?
basics
~20 sMaterialApp sets up app-wide services: the Navigator, the Theme, Material localizations and a root ScaffoldMessenger. Scaffold lays out one screen's Material slots. Scaffold.of fails when its context sits above the Scaffold, such as the widget that builds it.
In Flutter, how do you keep a long Text from spilling out of its space, and what do maxLines, overflow and softWrap each control?
basics
~20 sGive the Text a bounded width, then limit it with maxLines and choose how the cut is drawn with overflow (clip, fade, ellipsis or visible). softWrap decides whether text may break onto new lines at all; it defaults to true.
In Flutter, how do you style widgets from the app theme instead of hardcoding colors and text styles?
basics
~10 sDefine one ThemeData, usually with a ColorScheme and a TextTheme, pass it to MaterialApp's theme, then read Theme.of(context).colorScheme and .textTheme in widgets instead of writing Colors.blue or a literal TextStyle.
In Flutter, where should a TextFormField's TextEditingController be created and disposed, and what breaks if build() creates it?
basics
~20 sCreate a TextEditingController once per State, as a field initializer or in initState, and call its dispose() in dispose(). Created inside build(), every rebuild hands the field a fresh empty controller, losing the typed text, and the old ones are never disposed.
In Flutter, how do you bundle offline JSON question packs and sound files with an app and read them at runtime?
basics
~20 sList the files or directories under flutter: assets: in pubspec.yaml, which copies them into the app's asset bundle, then read them by their declared path: rootBundle.loadString for text such as JSON, rootBundle.load for bytes such as sounds.
In Flutter, how do you bundle a custom font family in pubspec.yaml and apply it app-wide and to a single Text widget?
basics
~20 sCopy the font files into the project, list them in pubspec.yaml under flutter: fonts: as a family with asset entries, then pass that family name as fontFamily to ThemeData for the whole app or to a TextStyle for one widget.
In Flutter, how does the Icon widget draw Icons and CupertinoIcons glyphs, and what must pubspec.yaml declare for each set?
basics
~20 sIcon draws one character of an icon font. Icons entries are const IconData code points in the MaterialIcons font, bundled only with uses-material-design: true; CupertinoIcons use the CupertinoIcons font from the cupertino_icons package, which must be a dependency.
In Flutter, how do Image.asset, Image.network, Image.file and Image.memory differ, and what do all four have in common?
basics
~20 sEach constructor wraps a different ImageProvider: AssetImage for bundled files, NetworkImage for URLs, FileImage for device files and MemoryImage for bytes. All decode through the same in-memory ImageCache and accept cacheWidth, cacheHeight, the loading, frame and error builders, and gaplessPlayback.
In Flutter, how are 2.0x and 3.0x image asset variants chosen for a device, and what must pubspec.yaml declare?
basics
~20 sPut higher-resolution copies in sibling folders such as 2.0x/ and 3.0x/ and declare only the main asset or its directory; Flutter bundles the variants, and AssetImage picks the one closest to the device pixel ratio, rendering it at the main asset's logical size.
In Flutter, what do FutureBuilder and StreamBuilder do, and how should a builder render loading, error and data from an AsyncSnapshot?
basics
~10 sFutureBuilder and StreamBuilder subscribe to a Future or Stream and rebuild with an AsyncSnapshot describing its latest state. The builder checks snapshot.hasError, then hasData, and otherwise shows a loading indicator.
In Flutter, what distinguishes ephemeral state from app state, and where should a password field's show/hide toggle live?
basics
~20 sEphemeral state belongs to one widget — a visibility toggle, the selected tab — and lives in its State behind setState. App state is shared across screens or kept between sessions, like the signed-in user. The password toggle is ephemeral.
In Flutter, what is a ChangeNotifier, and how does a ListenableBuilder rebuild when that notifier calls notifyListeners()?
basics
~10 sChangeNotifier is a foundation class that holds mutable state outside widgets and calls its registered listeners when notifyListeners() runs. ListenableBuilder subscribes to it and calls setState internally, so only the builder's subtree rebuilds.
In Flutter, why does a weather screen whose FutureBuilder calls fetchWeather() inside build() refetch on every rebuild, and how do you fix it?
basics
~20 sEach build() call runs fetchWeather() again and passes FutureBuilder a new Future, so it resubscribes, shows waiting and fires another request. Create the future once in a State field or initState and pass that field.
In Flutter, how do Provider, Riverpod and BLoC differ on state scope, testability, boilerplate and async handling?
basics
~20 sProvider scopes objects to the widget tree and looks them up by type through BuildContext. Riverpod keeps state in a ProviderContainer, readable without BuildContext and overridable in tests. BLoC turns events into a stream of states: most boilerplate, most explicit.
In a Flutter app, what is constructor injection, and how does it let a test swap a real payment service for a fake?
basics
~10 sConstructor injection means a class receives its dependencies as constructor parameters instead of creating or looking them up. A test builds the class itself and passes a FakePaymentService where production passes the real one.
How does the official Flutter architecture guide's Compass app organize lib/, and why does it mix feature-first and layer-first folders?
basics
~20 sThe Compass app groups lib/ui by feature, because each feature has one view and one view model, but groups lib/data by type, because repositories and services are shared across features. Domain models sit in lib/domain, used by both layers.
In Flutter's official architecture guide, what are views, view models, repositories and services, and which layer does each belong to?
basics
~20 sFlutter's architecture guide puts views (compositions of widgets) and view models (UI state and UI logic) in the UI layer, and repositories (the source of truth per data type) and services (stateless wrappers around external APIs) in the data layer.
Why does Flutter's architecture guide return a sealed Result<T> of Ok or Error from services and repositories instead of throwing exceptions?
basics
~20 sDart methods never declare what they throw, so callers forget to catch. A sealed Result<T> puts failure in the return type: the caller must unwrap Ok or Error, typically with a switch, before it can use the value.
With get_it, how do registerSingleton, registerLazySingleton and registerFactory differ in when the object is created and how many instances exist?
basics
~20 sregisterSingleton stores an instance you already built, returned on every get; registerLazySingleton runs its factory on the first get and reuses that one object; registerFactory runs its factory on every get, returning a new object each time.
In Flutter, why is calling setState from an AnimationController listener on every tick discouraged, and what replaces it?
basics
~20 ssetState in a controller listener re-runs the State's whole build method every frame, rebuilding widgets that never change. AnimatedBuilder or a FooTransition widget scopes the rebuild to what depends on the animation, and FadeTransition avoids widget rebuilds altogether.
In a Flutter StatefulWidget, how do you create, start, stop and dispose an AnimationController for a pulsing record button?
basics
~20 sMix a ticker provider into the State, create the controller in initState with vsync: this and a duration, call repeat(reverse: true) while recording, stop or animate it back when recording ends, and dispose it in dispose before super.dispose().
In Flutter, how does a Hero animation carry a widget between two routes, and what must the two Hero widgets share?
basics
~20 sThe app's HeroController pairs Hero widgets with equal tags on the outgoing and incoming PageRoutes. During the route transition, the destination hero's child flies in the Navigator's overlay between their bounds while placeholders fill both original slots.
In Flutter, how does AnimatedContainer animate a property change, and when do you need an AnimationController instead of an implicit widget?
basics
~20 sAnimatedContainer's State keeps its own AnimationController; when a rebuild passes a new property value it tweens from the current value to it over duration and curve. Loops, on-demand playback, gestures and shared timelines need an explicit controller.
In Flutter's animation library, what does a Tween do, and how does Tween.animate() relate to Animation.drive()?
basics
~10 sA Tween is an Animatable that maps a 0.0-to-1.0 animation value onto a begin-to-end range of sizes, colors or offsets. tween.animate(controller) and controller.drive(tween) are the same operation written from opposite ends.
In a Flutter mobile app, how do you dismiss the soft keyboard when the user taps outside a TextField or scrolls?
basics
~10 sMove focus off the text field with FocusManager.instance.primaryFocus?.unfocus(), called from TextField.onTapOutside or a background tap, and set keyboardDismissBehavior to onDrag on scroll views. On touch Android and iOS, Flutter's defaults do neither.
In Flutter, when do you use GestureDetector versus InkWell for a tappable sticker, and what does InkWell add on top?
basics
~20 sGestureDetector recognizes gestures and draws nothing; InkWell, from the Material library, wraps one and adds an ink splash painted on the nearest Material, focus with keyboard activation, hover and focus colours, and a disabled state when onTap is null.
In Flutter's gesture arena, how is a tap on an email tile resolved against the enclosing PageView's horizontal drag for the same pointer?
basics
~20 sBoth recognizers join the pointer's arena on pointer down. If the finger moves past the touch slop, the drag declares victory and the tap is rejected; if not, the arena is swept on pointer up and its first member, the innermost tap, wins.
In Flutter, who should create and dispose a FocusNode, and what breaks when one is created inside build()?
basics
~20 sA FocusNode is a long-lived object owned by a State: create it once and call dispose() in State.dispose. Creating one in build() swaps in a fresh node on every rebuild, leaking old nodes and dropping focus mid-typing.
In Flutter, why does a GestureDetector around a padded sticker miss taps on its padding, and what do HitTestBehavior opaque, translucent and deferToChild change?
basics
~20 sWith a child, GestureDetector defaults to HitTestBehavior.deferToChild, so it is hit only where a descendant is hit and padding misses. opaque claims its whole box and blocks targets behind; translucent claims it but lets targets behind be hit too.
In Flutter, how do you give an icon-only button and a decorative image the right screen-reader announcement?
basics
~10 sGive the icon button a tooltip, or its Icon a semanticLabel, so TalkBack and VoiceOver read a name plus "button". Hide a purely decorative image with Image's excludeFromSemantics: true, or wrap it in ExcludeSemantics.
In Flutter, what replaced textScaleFactor, and how should a widget read and apply the user's font size setting?
basics
~10 sTextScaler replaced the double textScaleFactor, because Android 14 scales large text less than small text. Text applies MediaQuery.textScalerOf(context) automatically; custom code calls scaler.scale(fontSize) instead of multiplying by a factor.
In Flutter 3.47, what does it take to set up gen-l10n so .arb files become an AppLocalizations class wired into MaterialApp?
basics
~10 sAdd flutter_localizations (from the SDK) and intl, set flutter: generate: true in pubspec.yaml, add l10n.yaml and the .arb files, then pass AppLocalizations.localizationsDelegates and AppLocalizations.supportedLocales to MaterialApp. The generated Dart lands in your source tree.
In Flutter, what do MergeSemantics and ExcludeSemantics do to the semantics tree, and when do you use each?
basics
~10 sMergeSemantics folds a subtree's semantics into one node, so a checkbox and its Text are one focus stop read together. ExcludeSemantics removes a subtree from the semantics tree, so screen readers skip it entirely.
In a Flutter app using gen-l10n, how do you show a translated string in a widget, and why does AppLocalizations.of(context) usually need a !?
basics
~20 sCall AppLocalizations.of(context) from a widget below MaterialApp and read the generated getter or method, such as cartTitle. It returns a nullable type because gen-l10n's nullable-getter option defaults to true, so call sites add ! unless that option is false.
In a Flutter app using graphql_flutter, how do you build a GraphQLClient and make it available to Query and Mutation widgets?
basics
~10 sChain an AuthLink onto an HttpLink, give GraphQLClient that link and a GraphQLCache (HiveStore for persistence, after await initHiveForFlutter()), wrap it in a ValueNotifier and pass it to a GraphQLProvider above MaterialApp.
In Flutter with package:http, how do you send a GET and a JSON POST, and why reuse one http.Client instead of calling http.get each time?
basics
~10 sCall client.get(uri) or client.post(uri, headers: {'Content-Type': 'application/json'}, body: jsonEncode(data)) on one long-lived http.Client and check response.statusCode. The top-level http.get creates and closes a new Client for every call, losing persistent connections.
In Flutter, why can't connectivity_plus's onConnectivityChanged stream tell you whether your API is reachable, and how should an app use it instead?
basics
~20 sconnectivity_plus reports which network interfaces are up (wifi, mobile, none), not whether packets reach your server. Captive portals, dead DNS or a down backend all look connected, so treat it as a hint and let the real request decide.
In a Flutter app, how do you turn a decoded JSON API response into a typed Dart model, and why not pass Map<String, dynamic> around?
basics
~20 sGive the model class a factory fromJson(Map<String, dynamic>) that casts each key into a typed final field, and a toJson() that builds the map back. Raw maps push every typo and type mismatch to runtime, far from the API call.
In Flutter with web_socket_channel, how do you open a WebSocket, receive and send messages, and close it when the screen goes away?
basics
~10 sCall WebSocketChannel.connect(uri), await channel.ready, listen to channel.stream for incoming messages and call channel.sink.add to send. In the State's dispose, cancel the subscription and call channel.sink.close().
In Flutter's path_provider, how do the documents, support, temporary and cache directories differ, and what does each map to on iOS and Android?
basics
~20 sDocuments holds user-generated or unrecreatable data, support holds app-private files, and temporary and cache hold re-creatable data the OS may clear. On iOS they map to Documents, Application Support and Caches; on Android to app_flutter, files and the cache dir.
In Flutter, what is shared_preferences meant to store, which value types does it accept, and what should never go into it?
basics
~20 sshared_preferences holds small, non-critical settings as int, double, bool, String or List<String>, backed by NSUserDefaults, Android DataStore or SharedPreferences, and localStorage on web. Never store secrets, large data or records you cannot afford to lose.
In a Flutter app, why does a refresh token belong in flutter_secure_storage rather than shared_preferences, and where does each platform keep it?
basics
~20 sshared_preferences writes plain values to an app file anyone with file access can read, while flutter_secure_storage encrypts them with keys held by the OS: the Keychain on iOS and macOS, Keystore-wrapped AES keys on Android.
In a Flutter app using Drift, how does a query's watch() stream know to re-emit after a write, and where does that mechanism break down?
basics
~20 sDrift records which tables each watched query reads; every insert, update or delete made through drift's APIs marks those tables changed, and affected queries re-run and emit. Writes that bypass drift's notifications, such as customStatement or another connection, trigger nothing.
With sqflite, how do openDatabase's version, onCreate and onUpgrade work together when an app adds a column to an existing table in version 2?
basics
~20 sopenDatabase compares the requested version with the file's stored version. A new file runs onCreate, which must build the full current schema; an older file runs onUpgrade(db, oldVersion, newVersion) once, where you apply each step, such as ALTER TABLE ADD COLUMN.
With Flutter's firebase_analytics, how do you log a custom funnel event and a user property, and which naming rules apply?
basics
~10 sFirebaseAnalytics.instance.logEvent(name: 'lesson_completed', parameters: {...}) logs an event whose parameter values are String or num; setUserProperty(name:, value:) tags the user. Reserved names and the firebase_ prefix throw ArgumentError.
With firebase_auth in Flutter, how do you sign a user in with signInWithEmailAndPassword and handle the FirebaseAuthException it can throw?
basics
~10 sAwait FirebaseAuth.instance.signInWithEmailAndPassword(email:, password:) inside try, catch FirebaseAuthException and switch on e.code. With email enumeration protection, wrong email or password both arrive as invalid-credential, not user-not-found or wrong-password.
With Flutter's firebase_remote_config, how does a parameter move from setDefaults through fetch and activate to what getBool returns?
basics
~20 ssetDefaults supplies in-app values; fetch() downloads backend values into a cache without applying them; activate() makes them what getBool and the other getters return. fetchAndActivate() does both and returns true only when new values were activated.
In Flutter's cloud_firestore plugin, what is the difference between get() and snapshots() on a DocumentReference or query, and when do you use each?
basics
~20 sget() returns a Future with one snapshot, trying the server, then the cache. snapshots() returns a Stream that emits current data at once and on every change, local writes included. Use get() for one-off reads, snapshots() for live screens.
In a Flutter app using FlutterFire, why must main() await Firebase.initializeApp before runApp, and what breaks when that order slips?
basics
~10 sEvery FlutterFire plugin looks up a FirebaseApp that exists only after Firebase.initializeApp completes. So main() calls WidgetsFlutterBinding.ensureInitialized(), awaits initializeApp with DefaultFirebaseOptions.currentPlatform, then calls runApp; otherwise the first plugin call throws [core/no-app].
In Flutter, what is a MethodChannel for, and how does a Dart call such as reading the battery-saver state reach host code and come back?
basics
~20 sA MethodChannel is a named, asynchronous pipe from Dart to host code: invokeMethod encodes a method name and arguments, the Kotlin or Swift handler registered under the same channel name replies, and Dart awaits the result as a Future.
With Flutter's permission_handler package, how do you request microphone permission and handle each status the request can return?
basics
~10 sDeclare RECORD_AUDIO in AndroidManifest.xml and NSMicrophoneUsageDescription in Info.plist, call Permission.microphone.request(), then branch: granted proceeds, denied can be asked again later, permanentlyDenied needs openAppSettings(), restricted cannot be changed.
In Flutter, what is the difference between a plain Dart package and a plugin package, and how does pubspec.yaml mark a package as a plugin?
basics
~20 sA plain Dart package ships only Dart code. A plugin package also ships host-platform code (Kotlin or Java, Swift or Objective-C, C++, or web Dart) and declares it per platform under flutter: plugin: platforms: in pubspec.yaml, so the Flutter tool registers it at build time.
In Flutter, how do PlatformException and MissingPluginException from MethodChannel.invokeMethod differ, and what usually causes each one?
basics
~10 sPlatformException means a host handler ran and replied with an error (code, message, details). MissingPluginException means the reply was empty: no handler on that channel name, or the handler answered notImplemented.
In Flutter, what are the five AppLifecycleState values, and what does each one mean on Android and iOS?
basics
~10 sAppLifecycleState has resumed (visible, focused), inactive (visible, unfocused), hidden (no view visible), paused (not visible, no frames, mobile only) and detached (engine without a view, also the initial state).
What are Flutter's debug, profile and release build modes, and when do you use each one?
basics
~20 sDebug mode is for development: asserts, service extensions, a debugger and hot reload, but slow. Profile mode is AOT-compiled like release with tracing so you can measure performance on a device. Release mode is optimized, with asserts and debugging off, for users.
In Flutter, what is the difference between hot reload, hot restart and a full restart, and when do you need each?
basics
~20 sHot reload injects changed Dart code and rebuilds widgets while keeping state; hot restart reloads the code and reruns main(), losing state; a full restart rebuilds native code too and is needed after Kotlin, Swift or plugin changes.
In Flutter DevTools, how do you use the Widget Inspector's Select Widget Mode to find which widget draws a given element on screen?
basics
~20 sTurn on Select Widget Mode in the DevTools Flutter inspector and tap the element in the running debug app; the inspector selects that widget, scrolls the widget tree to it, and shows its size, constraints and properties in the Widget Explorer.
In Flutter, what is the difference between print() and debugPrint(), and why does debugPrint exist at all?
basics
~20 sprint() writes each message straight to the console. debugPrint() is Flutter's throttled wrapper: it queues lines and releases about 12 KB of text, then pauses a second, so Android does not drop log lines. Both still print in release builds.
Why should a Flutter team never judge a janky screen's performance in debug mode, and what should they do instead?
basics
~20 sDebug builds run JIT-compiled code with assertions and debug-only work on every frame, so their timings are unrepresentative and unevenly distorted. Reproduce the jank with flutter run --profile on a physical device, then measure and optimize there.
In Flutter, what does the compute() function do, and how would you use it to parse a large JSON file without freezing the UI?
basics
~20 scompute(callback, message) runs callback(message) on a new background isolate and returns a Future with the result, so heavy CPU work such as jsonDecode plus model mapping no longer blocks the main isolate that builds and schedules frames.
In Flutter, why does a const widget inside a build method skip rebuilding when its parent rebuilds, and when does it still rebuild?
basics
~10 sA const constructor call yields the same canonical instance on every build, and Element.updateChild leaves an identical child untouched. Its subtree is skipped unless an inherited dependency or its own state marks it dirty.
In Flutter, how do you measure what makes up a release app's size, and why are debug builds and upload packages misleading?
basics
~20 sBuild a release with --analyze-size (one ABI on Android), read the terminal summary, then open the generated code-size-analysis JSON in the DevTools app size tool. Debug builds carry JIT overhead, and upload packages hold content the stores strip per device.
In Flutter DevTools' frame chart, what do the UI and raster bars of a frame measure, and how do you tell which one made a frame janky?
basics
~20 sEach frame has a UI bar (Dart work) and a raster bar (the engine drawing the scene). Each must fit the budget, about 16 ms at 60 Hz or 8 ms at 120 Hz; the bar over it points to the cause.
In Flutter, why is wrapping a subtree in an Opacity widget with a value like 0.5 costly, and what cheaper options exist?
basics
~20 sA fractional Opacity makes Flutter paint the child into an offscreen buffer (a saveLayer) and composite it back, which costs raster time. Cheaper: put the alpha in the color, use Image's color or opacity parameters, or Visibility for on/off.
In Flutter's flutter_test, how do you write a widget test proving a login form shows its validation messages when submitted empty?
basics
~10 sCall testWidgets, build the form with tester.pumpWidget inside a MaterialApp, tap the submit button through a finder, call tester.pump() so the rebuild happens, then expect find.text('Email is required') to match findsOneWidget.
With mocktail in a Flutter test, how do you stub a dependency's async method and then verify the code under test called it?
basics
~10 sDeclare class MockWeatherApi extends Mock implements WeatherApi, stub with when(() => api.fetchForecast('Oslo')).thenAnswer((_) async => forecast), run the code, then assert with verify(() => api.fetchForecast('Oslo')).called(1).
In a Flutter widget test, what is the difference between tester.pump() and tester.pumpAndSettle(), and when is each the right call?
basics
~20 stester.pump() renders one frame, optionally after advancing fake time by a duration; tester.pumpAndSettle() keeps pumping in 100 ms steps until no frame is scheduled. Use pump for precise control and pumpAndSettle to finish finite animations.
In Flutter, how does a golden test with matchesGoldenFile work, and how do you create or refresh its baseline image?
basics
~20 smatchesGoldenFile renders the widget a finder locates, encodes it as PNG and compares it pixel for pixel with a stored file. Running flutter test --update-goldens writes the current rendering as the new baseline instead of comparing.
In Flutter, how does an integration_test test differ from a widget test, and how do you write and run one on an Android emulator?
basics
~20 sAn integration_test test uses the same testWidgets and finder API, but runs the real app on a device or emulator in real time with real plugins. Call IntegrationTestWidgetsFlutterBinding.ensureInitialized() first and run flutter test integration_test with -d.
For a Flutter app's first Google Play release, why build with flutter build appbundle rather than flutter build apk, and when does --split-per-abi matter?
basics
~20 sflutter build appbundle produces an .aab from which Google Play generates per-device APKs, and new Play apps must upload a bundle; --split-per-abi matters only when shipping APKs elsewhere, replacing one fat APK with one APK per ABI.
In a Flutter CI pipeline run on every merge, which Flutter and Dart commands form the stages, and what fails each one?
basics
~20 sA Flutter pipeline runs flutter pub get --enforce-lockfile, dart format --output=none --set-exit-if-changed, flutter analyze, flutter test, then flutter build appbundle and flutter build ipa; each exits non-zero on drift, formatting, analyzer issues, failures or build errors.
In Flutter, what does flutter build ipa produce, and how does that output reach App Store Connect?
basics
~10 sflutter build ipa archives the app in release mode into an .xcarchive under build/ios/archive, then exports a signed App Store .ipa into build/ios/ipa; you upload that .ipa with Transporter, xcrun altool or Xcode.
In a Flutter pubspec.yaml, what does version: 1.2.3+4 become in the Android and iOS builds?
basics
~10 sThe part before + (1.2.3) is the build name, used as Android versionName and iOS CFBundleShortVersionString; the part after + (4) is the build number, used as Android versionCode and iOS CFBundleVersion.
How do you configure release signing for a Flutter Android app using an upload keystore, key.properties and signingConfigs in build.gradle.kts?
basics
~20 sCreate an upload keystore with keytool, describe it in android/key.properties (storePassword, keyPassword, keyAlias, storeFile), load that file in android/app/build.gradle.kts, create a release signingConfig from it, and point the release build type at it instead of the debug key.
Which renderers does Flutter 3.47 use on the web, and how does an app end up on CanvasKit or skwasm?
basics
~20 sFlutter web draws with Skia in two builds: CanvasKit, used by the default JavaScript output of flutter build web, and skwasm, used when the app is built with --wasm and the browser can run it. The HTML renderer is gone.
In a Flutter desktop app, where do you set the initial window size and title, and why is that not in Dart code?
basics
~20 sEach desktop target has a generated native runner that creates the OS window before Dart runs: windows/runner/main.cpp, linux/runner/my_application.cc and the macOS MainMenu.xib window. Size and title are set there; the Dart windowing API is still experimental.
Why does a sandboxed Flutter macOS app fail network calls with Operation not permitted, and which entitlement files must you edit?
basics
~10 sFlutter macOS apps are sandboxed by default, and outgoing connections need com.apple.security.network.client, which the template omits. Add it to both macos/Runner/DebugProfile.entitlements and Release.entitlements, keeping them in step.
In a Flutter 3.47 desktop app, why do Material buttons show an arrow cursor, and how do you give a custom row a hand cursor?
basics
~20 sSince Flutter 3.41, Material buttons and InkWell use WidgetStateMouseCursor.adaptiveClickable: a hand on the web, the basic arrow on desktop. For a custom row, wrap it in MouseRegion with cursor: SystemMouseCursors.click and track hover in onEnter and onExit.