Flutter

Flutter is Google's UI toolkit for building cross-platform apps — iOS, Android, web, and desktop — from a single Dart codebase. Unlike approaches that wrap native components, Flutter draws every pixel itself with its own rendering engine, which gives it remarkably consistent UI across platforms and the freedom to build highly custom designs without fighting platform widgets.

The mental model is the widget tree: everything you see (and much you don't — layout, padding, gestures) is a widget, and the UI is rebuilt from your state. Internalize that, pick a state-management approach, and standardize it early — those two choices shape the whole codebase.

TL;DR

Quick Example

A widget rebuilds its UI from state when setState runs:

Core Concepts

State Management

Flutter's built-in setState works for local widget state, but apps need a strategy for shared state:

💡 The specific choice matters less than consistency — pick one and apply it across the team. See Mobile State Management.

Platform Integration

Best Practices

Common Mistakes

Expensive work inside build

Rebuilding the whole tree for a small change

FAQ

Flutter or React Native?

Both produce high-quality cross-platform apps. Flutter draws its own UI with a custom engine, giving extremely consistent, pixel-perfect, highly-custom interfaces and strong performance — at the cost of learning Dart. React Native uses JavaScript/React and renders to native components, which suits teams with React/web experience and a large JS ecosystem. Choose Flutter for custom UI consistency and performance; React Native for JS familiarity and ecosystem overlap with web.

Why does Flutter use its own rendering engine instead of native widgets?

Because rendering everything itself (via Skia/Impeller) gives Flutter complete control over every pixel, so the UI looks identical across platforms and you can build any custom design without being constrained by — or fighting — native widget sets. The tradeoff is that Flutter must reimplement platform look-and-feel (which it does well via Material/Cupertino widgets) and the engine adds to app size.

What state management should I choose?

For most modern apps, Riverpod is a strong default — type-safe, testable, and not tied to the widget tree. Bloc/Cubit suits teams wanting strict structure and event-driven flows. Provider is simpler and well-established. For small apps, setState plus a little InheritedWidget may be enough. The key is to pick one early and apply it consistently; mixing approaches creates confusion.

Do I need to learn Dart, and is that a barrier?

Yes, Flutter uses Dart — but it's an approachable, statically-typed language that feels familiar to anyone who knows Java, JavaScript, or C#. Most developers become productive quickly. Dart's features (sound null safety, async/await, strong tooling) are well-suited to UI work, and the learning curve is rarely the main obstacle — understanding the widget tree and state management usually takes more effort.

Related Topics

References