Flutter

Build beautiful, natively compiled apps for mobile, web, and desktop from a single codebase.

Dart Language Cross-Platform Hot Reload 60fps UI Open Source by Google
Scroll to explore
What is Flutter?

Flutter is Google's open-source UI toolkit for crafting natively compiled, beautiful applications across mobile, web, and desktop from a single Dart codebase.

📱

Mobile

iOS & Android apps with pixel-perfect native performance using a single codebase.

🌐

Web

Compile to JavaScript and run in any modern browser with full fidelity.

🖥

Desktop

Windows, macOS, and Linux native apps — all from the same project.

📺

Embedded

Smart TVs, automotive dashboards, and embedded displays via Flutter Embedder API.

🔥

Hot Reload

See changes instantly without losing app state — drastically speeds up development.

🎨

Rich Widgets

Material 3 & Cupertino widgets out of the box, fully customisable and composable.

Flutter Architecture

🏗
Your App Code (Dart)
Business logic, widgets, state management, navigation — all in Dart
🧩
Flutter Framework
Material / Cupertino widgets, Gestures, Animation, Painting, Rendering
⚙️
Flutter Engine (C++)
Skia / Impeller graphics engine, Dart VM, Text layout, Platform channels
🌉
Platform Embedder
iOS / Android / Web / Desktop — thin native glue layer
💻
Hardware / OS
GPU, CPU, native APIs, platform services
Key Insight: Flutter renders its own pixels via its graphics engine instead of using native UI components. This gives pixel-perfect consistency across every platform.

Why Choose Flutter?

Write once, deploy to iOS, Android, Web, Windows, macOS, and Linux. Reduces development cost by up to 50% compared to native development for each platform.
Flutter compiles to native ARM or x86 machine code using AOT (Ahead-of-Time) compilation. The Impeller rendering engine targets 60–120fps with no JavaScript bridge overhead.
Every pixel is controlled by Flutter. Custom themes, complex animations, custom painters — all achievable with fine-grained control. Material 3 is built-in.
pub.dev hosts 30,000+ packages. Backed by Google, used by Alibaba (Xianyu), BMW, eBay, Nubank, and many more Fortune 500 companies. An active GitHub community with thousands of contributors.
Hot reload & hot restart, excellent VS Code / Android Studio integration, the Flutter DevTools suite for profiling, widget inspection, memory analysis, and network monitoring.
Dart Language

Flutter uses Dart — a fast, type-safe, object-oriented language optimized for client-side development.

🔒

Sound Null Safety

Variables are non-nullable by default. The type system eliminates null-reference exceptions at compile time.

AOT + JIT

JIT compilation for fast dev cycles (hot reload). AOT for release builds — native speed performance.

🔄

Async / Await

First-class async support with Futures, Streams, and async/await syntax. No callback hell.

🧬

Strong Typing

Optional type annotations with full type inference. Generics, mixins, extension methods all supported.

Dart Fundamentals

Dart — Variables & Types
// Null safety: non-nullable by default
String name = 'Flutter';
int version = 3;
double rating = 4.9;
bool isAwesome = true;

// Nullable with ?
String? nickname;  // can be null

// Type inference with var / final / const
var message = 'Hello';        // inferred String
final pi = 3.14159;          // immutable at runtime
const maxItems = 100;        // compile-time constant

// Collections
List<String> fruits = ['apple', 'banana', 'mango'];
Map<String, int> scores = {'Alice': 95, 'Bob': 87};
Set<int> unique = {1, 2, 3};

// String interpolation
print('Hello, $name! Version ${version + 1}');
Dart — Functions & Classes
// Named & optional parameters
String greet(String name, {String greeting = 'Hello'}) {
  return '$greeting, $name!';
}

// Arrow functions
int square(int n) => n * n;

// Class with constructor
class Person {
  final String name;
  final int age;

  // Constructor shorthand
  Person({required this.name, required this.age});

  // Named constructor
  Person.anonymous() : name = 'Unknown', age = 0;

  // Getter
  bool get isAdult => age >= 18;

  // toString override
  @override
  String toString() => 'Person(name: $name, age: $age)';
}

// Mixins
mixin Flyable {
  void fly() => print('Flying!');
}

class SuperHero extends Person with Flyable {
  SuperHero(String name) : super(name: name, age: 30);
}
Dart — Async / Await & Streams
// Future — single async value
Future<String> fetchUser(int id) async {
  await Future.delayed(Duration(seconds: 2));
  return 'User $id';
}

void main() async {
  final user = await fetchUser(42);
  print(user);

  // Error handling
  try {
    final data = await riskyOperation();
  } catch (e) {
    print('Error: $e');
  }
}

// Stream — async sequence of values
Stream<int> countdown(int n) async* {
  for (int i = n; i >= 0; i--) {
    yield i;
    await Future.delayed(Duration(seconds: 1));
  }
}

// Listen to stream
countdown(5).listen((n) => print('$n...'));
Getting Started

Set up Flutter in minutes and create your first cross-platform app.

Install Flutter SDK

Download from flutter.dev/docs/get-started/install. Extract to a location like ~/flutter. Supports Windows, macOS, and Linux.

Add to PATH

Add export PATH="$PATH:~/flutter/bin" to your shell profile (.bashrc, .zshrc). Reload shell.

Run Flutter Doctor

Run flutter doctor to check all dependencies. It guides you to install Android SDK, Xcode, Chrome, etc.

Install an IDE

Use VS Code with the Flutter extension, or Android Studio with the Flutter & Dart plugins for the best DX.

Create a new project

Run flutter create my_app. This scaffolds a complete project with pubspec.yaml, lib/, test/, etc.

Run the app

Open a simulator or connect a device. Run flutter run to build and launch. Press r for hot reload!

Terminal
# Check Flutter installation
flutter doctor

# Create new project
flutter create my_awesome_app
cd my_awesome_app

# Get dependencies
flutter pub get

# Run on connected device/simulator
flutter run

# Build release APK for Android
flutter build apk --release

# Build for iOS
flutter build ios --release

# Build for web
flutter build web

# Add a package
flutter pub add http

Project Structure

Project Tree
my_app/
├── lib/                   # Your Dart code lives here
│   ├── main.dart         # App entry point
│   ├── screens/          # Screen widgets
│   ├── widgets/          # Reusable widgets
│   ├── models/           # Data models
│   ├── services/         # API / DB services
│   └── providers/        # State management
├── test/                  # Unit & widget tests
├── android/               # Android-specific files
├── ios/                   # iOS-specific files
├── web/                   # Web-specific files
├── assets/                # Images, fonts, JSON
└── pubspec.yaml           # Dependencies & metadata
Widgets

In Flutter, everything is a widget. From buttons to padding to the entire app — it's all composable widget trees.

Core Concept: A Flutter UI is a tree of widgets. Widgets describe what the UI should look like — Flutter's framework figures out how to render it efficiently.

Stateless vs Stateful

// StatelessWidget: immutable, no internal state
class GreetingCard extends StatelessWidget {
  const GreetingCard({
    super.key,
    required this.name,
  });

  final String name;

  @override
  Widget build(BuildContext context) {
    return Card(
      child: Padding(
        padding: const EdgeInsets.all(16),
        child: Text(
          'Hello, $name!',
          style: const TextStyle(fontSize: 24),
        ),
      ),
    );
  }
}
// StatefulWidget: has mutable internal state
class Counter extends StatefulWidget {
  const Counter({super.key});

  @override
  State<Counter> createState() => _CounterState();
}

class _CounterState extends State<Counter> {
  int _count = 0;

  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        Text('Count: $_count', style: TextStyle(fontSize: 32)),
        ElevatedButton(
          onPressed: () => setState(() => _count++),
          child: const Text('Increment'),
        ),
      ],
    );
  }
}

Essential Widget Catalogue

Layout

ColumnRowStackWrapGridViewListView

Arrange children vertically, horizontally, layered, or in a scrollable list/grid.

Containers

ContainerSizedBoxPaddingCenterAlign

Control size, color, decoration, padding, and alignment.

Material

ScaffoldAppBarCardDrawerBottomNav

Pre-built Material Design 3 components following Google's design spec.

Input

TextFieldCheckboxSwitchSliderForm

Collect user input with validation, decorations, and controllers.

Buttons

ElevatedButtonTextButtonIconButtonFAB

Various button types with ripple effects, icons, and custom styles.

Media

ImageIconCircleAvatarFadeInImage

Display images from assets, network, or memory. Built-in fade-in effects.

Widget Tree Anatomy

MaterialAppRoot app widget — theme, locale, routes
ScaffoldPage skeleton — AppBar, body, FAB, Drawer
ColumnVertical layout
Padding16px all sides
Text"Hello Flutter"
ElevatedButtononPressed callback
Icon + TextRow of label + icon
State Management

Choosing the right state management approach is crucial. Flutter offers many options — from simple setState to full-blown architectures.

ApproachBest ForLearning CurveBoilerplateReactive
setStateLocal widget state⭐ Low⭐ MinimalPartial
InheritedWidgetSimple prop passing⭐⭐ Medium⭐⭐ Some✓ Yes
ProviderSmall-medium apps⭐ Low⭐ Minimal✓ Yes
RiverpodMedium-large apps⭐⭐ Medium⭐⭐ Some✓ Yes
BLoCLarge / enterprise⭐⭐⭐ High⭐⭐⭐ High✓ Yes
GetXRapid prototyping⭐ Low⭐ Minimal✓ Yes
MobXReactive patterns⭐⭐ Medium⭐⭐ Some✓ Yes

Provider Example

Dart — Provider
// 1. Define a ChangeNotifier model
class CartModel extends ChangeNotifier {
  final List<String> _items = [];

  List<String> get items => List.unmodifiable(_items);

  void add(String item) {
    _items.add(item);
    notifyListeners();  // rebuilds listening widgets
  }

  void remove(String item) {
    _items.remove(item);
    notifyListeners();
  }
}

// 2. Provide it at the top of the tree
void main() => runApp(
  ChangeNotifierProvider(
    create: (_) => CartModel(),
    child: const MyApp(),
  ),
);

// 3. Consume with Consumer or context.watch
class CartButton extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final cart = context.watch<CartModel>();
    return Badge(
      label: Text('${cart.items.length}'),
      child: IconButton(
        icon: const Icon(Icons.shopping_cart),
        onPressed: () {},
      ),
    );
  }
}

Riverpod Example

Dart — Riverpod
import 'package:flutter_riverpod/flutter_riverpod.dart';

// Define a provider
final counterProvider = StateNotifierProvider<CounterNotifier, int>(
  (ref) => CounterNotifier(),
);

class CounterNotifier extends StateNotifier<int> {
  CounterNotifier() : super(0);
  void increment() => state++;
  void decrement() => state--;
}

// Wrap app with ProviderScope
void main() => runApp(ProviderScope(child: MyApp()));

// Use ConsumerWidget
class CounterScreen extends ConsumerWidget {
  @override
  Widget build(BuildContext ctx, WidgetRef ref) {
    final count = ref.watch(counterProvider);
    return Scaffold(
      body: Center(child: Text('$count', style: TextStyle(fontSize:48))),
      floatingActionButton: FloatingActionButton(
        onPressed: () => ref.read(counterProvider.notifier).increment(),
        child: const Icon(Icons.add),
      ),
    );
  }
}
Layout System

Flutter's layout is based on constraints flowing down and sizes bubbling up. Master it to build any UI imaginable.

Golden Rule: "Constraints go down, sizes go up, parent sets the position." Every widget receives constraints from its parent and reports back its final size.
Dart — Row & Column
Column(
  mainAxisAlignment: MainAxisAlignment.center,
  crossAxisAlignment: CrossAxisAlignment.start,
  children: [
    Text('Title', style: TextStyle(fontSize: 24)),
    const SizedBox(height: 8),
    Row(
      children: [
        Expanded(child: Text('Left')),   // takes available width
        Flexible(child: Text('Right')),  // flexible but won't force size
      ],
    ),
    Spacer(),  // fills remaining space
    ElevatedButton(onPressed: (){}, child: Text('OK')),
  ],
)
Dart — Stack, Positioned & Responsive
// Overlapping widgets with Stack
Stack(
  children: [
    Image.network('https://...', fit: BoxFit.cover),
    Positioned(
      bottom: 16, left: 16,
      child: Text('Caption', style: TextStyle(color: Colors.white)),
    ),
    Positioned(top: 8, right: 8, child: Icon(Icons.favorite)),
  ],
)

// Responsive with LayoutBuilder
LayoutBuilder(
  builder: (context, constraints) {
    if (constraints.maxWidth > 600) {
      return WideLayout();   // tablet/desktop
    }
    return NarrowLayout();   // phone
  },
)

// Adaptive sizing with MediaQuery
final screenWidth = MediaQuery.of(context).size.width;
final isTablet = screenWidth > 768;
Async & Networking

Flutter makes async operations first-class with FutureBuilder, StreamBuilder, and the http / dio packages.

Dart — HTTP & JSON
import 'dart:convert';
import 'package:http/http.dart' as http;

// Data model
class Post {
  final int id;
  final String title;
  final String body;

  const Post({required this.id, required this.title, required this.body});

  factory Post.fromJson(Map<String, dynamic> json) => Post(
    id: json['id'] as int,
    title: json['title'] as String,
    body: json['body'] as String,
  );
}

// Fetch from API
Future<List<Post>> fetchPosts() async {
  final response = await http.get(
    Uri.parse('https://jsonplaceholder.typicode.com/posts'),
  );
  if (response.statusCode == 200) {
    final data = jsonDecode(response.body) as List;
    return data.map((json) => Post.fromJson(json)).toList();
  }
  throw Exception('Failed to load posts');
}
Dart — FutureBuilder Widget
class PostsList extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return FutureBuilder<List<Post>>(
      future: fetchPosts(),
      builder: (context, snapshot) {
        // Loading state
        if (snapshot.connectionState == ConnectionState.waiting) {
          return const Center(child: CircularProgressIndicator());
        }
        // Error state
        if (snapshot.hasError) {
          return Center(child: Text('Error: ${snapshot.error}'));
        }
        // Data state
        final posts = snapshot.data!;
        return ListView.builder(
          itemCount: posts.length,
          itemBuilder: (ctx, i) => ListTile(
            title: Text(posts[i].title),
            subtitle: Text(posts[i].body),
          ),
        );
      },
    );
  }
}
Sample Projects

Complete, copy-ready Flutter code samples you can drop into your project.

🛍 Shop App●●●
🎧 Wireless Headphones
$79.99 · ⭐4.8 · Free shipping
⌚ Smart Watch Pro
$199.99 · ⭐4.6 · In stock
📱 Phone Case
$19.99 · ⭐4.9 · Limited
🛒 View Cart (3)
+
Dart — Complete App with BottomNav
import 'package:flutter/material.dart';

void main() => runApp(const MyApp());

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.blue),
        useMaterial3: true,
      ),
      home: const MainScreen(),
    );
  }
}

class MainScreen extends StatefulWidget {
  const MainScreen({super.key});

  @override
  State<MainScreen> createState() => _MainScreenState();
}

class _MainScreenState extends State<MainScreen> {
  int _selectedIndex = 0;

  static const _screens = [
    HomeTab(), SearchTab(), ProfileTab(),
  ];

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: IndexedStack(     // preserves tab state
        index: _selectedIndex,
        children: _screens,
      ),
      bottomNavigationBar: NavigationBar(
        selectedIndex: _selectedIndex,
        onDestinationSelected: (i) => setState(() => _selectedIndex = i),
        destinations: const [
          NavigationDestination(icon: Icon(Icons.home), label: 'Home'),
          NavigationDestination(icon: Icon(Icons.search), label: 'Search'),
          NavigationDestination(icon: Icon(Icons.person), label: 'Profile'),
        ],
      ),
    );
  }
}
Dart — Custom Animated Widget
class AnimatedHeartButton extends StatefulWidget {
  const AnimatedHeartButton({super.key});

  @override
  State<AnimatedHeartButton> createState() => _AnimatedHeartButtonState();
}

class _AnimatedHeartButtonState extends State<AnimatedHeartButton>
    with SingleTickerProviderStateMixin {
  late AnimationController _controller;
  late Animation<double> _scaleAnim;
  bool _liked = false;

  @override
  void initState() {
    super.initState();
    _controller = AnimationController(
      vsync: this,
      duration: const Duration(milliseconds: 200),
    );
    _scaleAnim = Tween(begin: 1.0, end: 1.4).chain(
      CurveTween(curve: Curves.elasticOut),
    ).animate(_controller);
  }

  void _onTap() {
    setState(() => _liked = !_liked);
    _controller.forward().then((_) => _controller.reverse());
  }

  @override
  Widget build(BuildContext context) {
    return GestureDetector(
      onTap: _onTap,
      child: ScaleTransition(
        scale: _scaleAnim,
        child: Icon(
          _liked ? Icons.favorite : Icons.favorite_border,
          color: _liked ? Colors.red : Colors.grey,
          size: 32,
        ),
      ),
    );
  }

  @override
  void dispose() {
    _controller.dispose();
    super.dispose();
  }
}
Dart — CustomPainter (Canvas Drawing)
class WaveWidget extends StatefulWidget { ... }

class WavePainter extends CustomPainter {
  final double animValue;
  WavePainter(this.animValue);

  @override
  void paint(Canvas canvas, Size size) {
    final paint = Paint()
      ..color = Colors.blue.withOpacity(0.5)
      ..style = PaintingStyle.fill;

    final path = Path();
    path.moveTo(0, size.height * 0.5);

    for (double x = 0; x <= size.width; x++) {
      final y = size.height * 0.5 +
          math.sin((x / size.width * 2 * math.pi) + animValue) * 30;
      path.lineTo(x, y);
    }
    path.lineTo(size.width, size.height);
    path.lineTo(0, size.height);
    path.close();

    canvas.drawPath(path, paint);
  }

  @override
  bool shouldRepaint(WavePainter old) => old.animValue != animValue;
}
Best Practices

Write clean, performant, and maintainable Flutter apps by following these proven guidelines.

Feature-first folder structure: Organise code by feature (auth/, home/, cart/) not by type. Each feature owns its screens, widgets, models, and providers.

Separation of concerns: Keep business logic out of widgets. Use repositories for data access, use cases/services for business logic, and widgets purely for UI.

Const constructors: Mark every widget constructor const when possible. Flutter skips rebuilding const widgets even when the parent rebuilds — massive performance win.
Use keys wisely: Add keys to widgets in lists so Flutter can efficiently reorder/update them. Prefer ValueKey with a stable identifier.

Avoid rebuilding large subtrees: Split large build() methods into smaller widgets. Use Consumer / Selector with Provider to narrow rebuild scope.

ListView.builder over ListView: Always use ListView.builder for long lists — it lazily builds only visible items. Avoid ListView(children: [...]) with many items.

Image optimisation: Use cacheWidth/cacheHeight on Image.network. Use cached_network_image package for disk caching.
Prefer required over nullable: Use required parameters instead of nullable optionals. This makes API contracts explicit.

Never use ! blindly: The null assertion operator ! throws at runtime. Always verify with ??, ?., or guard clauses.

Handle all async errors: Every Future should have error handling. Use try/catch with async/await. Implement proper error states in your UI.
Theme everything: Never hardcode colors or text styles. Define all values in ThemeData and access via Theme.of(context).

Extract reusable widgets: If a UI block is used more than once, extract it into a widget with a clear API. This improves readability and testability.

Dispose controllers: Always dispose AnimationController, TextEditingController, ScrollController, StreamSubscription in dispose().

Accessibility: Wrap interactive widgets with Semantics. Add meaningful labels for screen readers. Test with TalkBack (Android) and VoiceOver (iOS).
Unit tests: Test Dart logic in isolation — models, view models, repositories. No Flutter framework needed.

Widget tests: Use testWidgets() to render widgets in a test harness. Verify widget trees, tap events, text content.

Integration tests: Use integration_test package for full app flows on real devices/emulators.

Golden tests: Capture pixel-perfect screenshots with matchesGoldenFile() to catch unintended visual regressions.
Vet your packages: Check pub.dev scores, GitHub activity, issue count, and pub points before adding dependencies. Prefer Flutter-team maintained packages.

Minimise dependencies: Every package is a potential vulnerability and breaking change. Only add packages that provide real value.

Pin versions carefully: Use caret ranges (^1.0.0) for stability. Run flutter pub outdated regularly and update dependencies in a dedicated PR.

Essential Packages

🌐 Networking

httpdioretrofit

HTTP requests, interceptors, auth headers, file upload/download.

🔄 State

riverpodproviderbloc

Manage app state predictably and efficiently.

🗃 Storage

hiveisarsqfliteshared_prefs

Local persistence for preferences, structured data, and offline support.

🗺 Navigation

go_routerauto_route

Declarative routing with deep linking, shell routes, guards.

🖼 Images

cached_network_imageflutter_svg

Efficient image caching, SVG rendering, image manipulation.

🎭 UI/UX

lottieshimmerfl_chart

Lottie animations, skeleton loading, beautiful charts and graphs.

Flutter vs Alternatives

How does Flutter stack up against React Native, Xamarin, and native development?

FeatureFlutterReact NativeXamarinNative
LanguageDartJavaScript / TypeScriptC# / .NETSwift / Kotlin
RenderingOwn engine (Skia/Impeller)Native UI bridgeNative UI bridgeNative
PerformanceExcellentGoodGoodBest
UI ConsistencyPixel-perfectPlatform-variesPlatform-variesPlatform-native
Hot Reload✓ Yes✓ Yes✗ Limited✗ No
Desktop Support✓ Stable✓ Experimental✓ YesPlatform-specific
Web Support✓ Yes✓ Yes✗ No✗ No
Package EcosystemLarge (pub.dev)Very Large (npm)MediumPlatform-rich
Learning CurveMedium (Dart)Low (JS)Medium (C#)High (per platform)
Company BackingGoogleMetaMicrosoftApple / Google
When to pick Flutter: You want pixel-perfect custom UI, target 3+ platforms, have a Dart-friendly team, or need high-performance animations. When to consider React Native: Your team is strong in JavaScript/React and you want tight native component integration.

Flutter Version History

Flutter 1.0 (Dec 2018)

Initial stable release. Mobile (iOS & Android) only. Introduced Dart 2 and the material widget library.

Flutter 2.0 (Mar 2021)

Web & desktop in stable channel. Null safety. New Navigator 2.0 API. Over 200 new APIs.

Flutter 3.0 (May 2022)

macOS & Linux apps stable. Impeller renderer preview. Material 3 support. Casual games toolkit.

Flutter 3.16+ (2023-24)

Impeller as default on iOS. Dart 3 with records, patterns & sealed classes. Improved Wasm support for web.