Flutter

On this page 7

Flutter is an open-source cross-platform UI toolkit that lets developers build mobile apps for iOS and Android, and also web and desktop apps, from a single Dart codebase. In app development, its defining trait is that it does not wrap the platform’s native widgets: it draws the entire interface itself with its own rendering engine.

This design gives Flutter apps a consistent look and behavior on every platform and predictable performance, at the cost of a larger app binary and a layer of abstraction between the app and the native mobile operating system.

How Flutter renders an interface

A Flutter app is written in Dart and organized as a tree of widgets, which are lightweight, immutable descriptions of the interface. When state changes, Flutter rebuilds the affected widgets, compares them with the existing element tree, and updates only the render objects that actually changed.

The render objects compute layout and paint into layers, which the Flutter engine rasterizes on the GPU. Current releases use the Impeller renderer on iOS and on modern Android devices; it precompiles shaders to avoid the first-run animation stutter that older Skia-based builds suffered from.

The following table lists the three trees and their responsibilities.

TreeWhat it holdsLifetime
Widget treeImmutable configuration of the interfaceRebuilt often, cheap to create
Element treeMounted instances linking widgets to stateKept across rebuilds when possible
Render treeLayout, painting and hit testingUpdated only where something changed
The three trees in a Flutter app

Release builds are compiled ahead of time to native ARM code, while debug builds run on the Dart virtual machine with stateful hot reload, which injects code changes into a running app in about a second without losing its current state.

Flutter compared with other app development approaches

Flutter sits between fully native development and other cross-platform frameworks. The main difference from React Native is the rendering model: React Native maps components to real native views, while Flutter paints its own widgets that only imitate platform styles.

ApproachLanguageRenderingCode sharing
FlutterDartOwn engine draws every pixelOne codebase for all platforms
React NativeJavaScript or TypeScriptNative platform viewsMostly shared, native modules per platform
SwiftUISwiftNative, Apple platforms onlyShared across Apple devices
Jetpack ComposeKotlinNative, Android-firstShared across Android form factors
Native appSwift or KotlinPlatform toolkitSeparate codebase per platform
Flutter against neighboring approaches

SwiftUI and Jetpack Compose share Flutter’s declarative programming model, so the mental model of describing the interface as a function of state transfers well between them. The decisive difference is that the native toolkits receive new platform features first, while Flutter must wait for plugin or engine support.

Platform integration and plugins

Flutter reaches native features such as the camera, Bluetooth, payments or biometrics through plugins. A plugin combines Dart code with platform code in Swift or Kotlin, and the two sides communicate through platform channels, which pass asynchronous messages between the Dart isolate and the host platform.

For performance-critical calls, developers can use Dart FFI to invoke C libraries directly, and newer code-generation tools can create typed bindings to platform APIs. Native views, such as a map or a web view, can be embedded as platform views, but they carry composition overhead and should be used sparingly.

  • Pure Dart packages work everywhere and need no native code.
  • Federated plugins split one API into separate implementations per platform.
  • Custom platform channels suit one-off integrations with existing native modules.
  • Add-to-app embeds Flutter screens inside an existing native app.

When Flutter is a good choice

Flutter fits best when a team needs one product on several platforms with a custom, branded interface and limited native integration. It fits less well when an app depends heavily on the newest platform APIs or must feel exactly like the native system controls.

SituationRecommendationReason
Branded UI on iOS and AndroidFlutter is a strong fitIdentical design and one team
Small team, tight budgetFlutter is a strong fitOne codebase halves interface work
Heavy use of new OS featuresPrefer nativePlugins lag behind platform releases
Existing large native appAdd-to-app or stay nativeFull rewrite rarely pays off
Strict binary size limitsEvaluate carefullyEngine adds several megabytes
Existing JavaScript web teamConsider React NativeReuses language and skills
Decision guide for choosing Flutter

Limitations and common mistakes in Flutter projects

The most visible limitation is app size: the engine and framework typically add several megabytes to the download compared with a minimal native app. Accessibility and text input follow platform conventions well in most cases, but edge cases, such as specific keyboard behavior or screen reader nuances, may differ from native controls.

MistakeConsequenceBetter practice
Rebuilding large subtreesDropped frames during animationsSplit widgets and use const constructors
Heavy work on the main isolateUI freezes during parsingMove work to a background isolate
Uncontrolled plugin choiceAbandoned or insecure dependenciesAudit maintenance and platform support
Ignoring platform conventionsApp feels foreign to usersAdapt navigation and gestures per platform
Typical Flutter pitfalls

Frame budgets are strict: at 60 Hz a frame has about 16 ms, and at 120 Hz only about 8 ms. Profiling with the framework’s performance tools on a real mid-range device, not an emulator, is the reliable way to find jank.

The short version

Flutter is a way to build one app that works on both iPhone and Android phones. Instead of writing the app twice, developers write it once.

Most tools borrow the buttons and menus that each phone already has. Flutter instead paints everything on the screen itself, a bit like an artist who brings their own canvas and paints instead of rearranging furniture in each room. The app looks the same everywhere, but it carries its own painting kit, which makes it somewhat larger.

Where it makes a difference

A three-person startup builds a fitness coaching app with custom animated charts and a strong visual brand. Writing separate Swift and Kotlin apps would require at least two specialists, so the team chooses Flutter and ships the first version on both stores in about four months.

Hot reload shortens design iterations, and the charts look identical on every device. Health data integration needs plugins on each platform; one of them lags behind a new iOS release, so the team writes a small custom platform channel in Swift to cover the gap.

Profiling on a three-year-old Android phone reveals dropped frames in the workout timeline. Moving data processing to a background isolate restores smooth 60 frames per second, and the app launches with one shared codebase and a single interface team.