Flutter - Complete Development Guide

Master cross-platform mobile app development with Google's Flutter framework

What You'll Learn

Introduction to Flutter

Flutter is an open-source UI software development kit created by Google. It enables developers to build natively compiled applications for mobile (iOS & Android), web, and desktop from a single codebase.

Key Facts

  • Created by: Google (First stable release: December 2018)
  • Language: Dart
  • Current Version: 3.x (as of 2025)
  • Platforms: iOS, Android, Web, Windows, macOS, Linux
  • License: BSD 3-Clause

What Makes Flutter Different?

Unlike other cross-platform frameworks that use web views or native widgets, Flutter draws its own widgets using a high-performance rendering engine (Skia). This approach provides:

Why Choose Flutter?

Single Codebase

Write once, run everywhere. Build applications for mobile, web, and desktop from one codebase, reducing development time and maintenance costs.

Hot Reload

See changes instantly without losing app state. This feature dramatically speeds up development and makes experimentation easy.

Beautiful UI

Rich set of customizable widgets following Material Design and Cupertino (iOS) guidelines. Create stunning, brand-focused designs.

Native Performance

Compiled to native ARM code for mobile and to JavaScript for web. No JavaScript bridge overhead like React Native.

Strong Community

Backed by Google with active community support, thousands of packages, and extensive documentation.

Developer Productivity

Fast development cycles, excellent tooling, and clear documentation help teams ship features quickly.

When to Use Flutter

✅ Flutter is Great For:
  • MVP and startup applications needing quick market entry
  • Apps requiring consistent UI across platforms
  • Complex custom UI with animations
  • Apps with moderate platform-specific features
  • Real-time applications (chat, collaboration tools)
⚠️ Consider Alternatives When:
  • App heavily relies on platform-specific features
  • Team has deep expertise in native development
  • App size is critical (Flutter apps are typically 4-8MB larger)
  • Targeting only one platform with very specific requirements

Flutter Architecture

Flutter's architecture consists of three main layers:

1. Framework Layer (Dart)

The top layer where developers work. Contains:

2. Engine Layer (C/C++)

Provides low-level rendering using Skia graphics library, text layout, file/network I/O, and plugin architecture.

3. Embedder Layer (Platform-Specific)

Coordinates with the underlying operating system for rendering surfaces, accessibility, and input.

Key Insight: Flutter doesn't use platform widgets. It renders everything itself, giving developers complete control over the UI.

Dart Programming Language

Flutter uses Dart, a language optimized for building user interfaces. Key features include:

Basic Dart Syntax

// Variables
var name = 'Flutter';
String title = 'Developer';
int age = 5;
double version = 3.0;
bool isAwesome = true;

// Functions
String greet(String name) {
  return 'Hello, $name!';
}

// Arrow functions
int add(int a, int b) => a + b;

// Classes
class Developer {
  String name;
  int experience;

  Developer(this.name, this.experience);

  void code() {
    print('$name is coding with $experience years experience');
  }
}

// Lists and Maps
List<String> frameworks = ['Flutter', 'React Native', 'Ionic'];
Map<String, int> versions = {'Flutter': 3, 'Dart': 3};

// Null Safety (Dart 2.12+)
String? nullableString;  // Can be null
String nonNullString = 'Hello';  // Cannot be null

Why Dart for Flutter?

Flutter Widgets

Everything in Flutter is a widget. Widgets describe what the UI should look like given their current configuration and state.

Widget Types

1. Stateless Widgets

Immutable widgets that don't maintain any state.

class Greeting extends StatelessWidget {
  final String name;

  const Greeting({Key? key, required this.name}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Text('Hello, $name!');
  }
}

2. Stateful Widgets

Widgets that maintain mutable state that can change over time.

class Counter extends StatefulWidget {
  @override
  _CounterState createState() => _CounterState();
}

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

  void _increment() {
    setState(() {
      _count++;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        Text('Count: $_count'),
        ElevatedButton(
          onPressed: _increment,
          child: Text('Increment'),
        ),
      ],
    );
  }
}

Common Widgets

Layout Widgets

  • Container
  • Row / Column
  • Stack
  • Expanded / Flexible
  • Padding / Center

UI Widgets

  • Text
  • Image
  • Icon
  • Button (ElevatedButton, TextButton)
  • TextField

Interactive Widgets

  • GestureDetector
  • InkWell
  • ListView
  • GridView
  • Checkbox / Switch

Building Layouts

Flutter uses a compositional approach to build UIs. Widgets are nested to create complex layouts.

Basic Layout Example

class ProfileCard extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Container(
      padding: EdgeInsets.all(16.0),
      decoration: BoxDecoration(
        color: Colors.white,
        borderRadius: BorderRadius.circular(12.0),
        boxShadow: [
          BoxShadow(
            color: Colors.grey.withOpacity(0.2),
            spreadRadius: 2,
            blurRadius: 5,
          ),
        ],
      ),
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          Row(
            children: [
              CircleAvatar(
                radius: 30,
                backgroundImage: NetworkImage('https://example.com/avatar.jpg'),
              ),
              SizedBox(width: 16),
              Column(
                crossAxisAlignment: CrossAxisAlignment.start,
                children: [
                  Text(
                    'John Doe',
                    style: TextStyle(
                      fontSize: 20,
                      fontWeight: FontWeight.bold,
                    ),
                  ),
                  Text(
                    'Flutter Developer',
                    style: TextStyle(color: Colors.grey),
                  ),
                ],
              ),
            ],
          ),
          SizedBox(height: 16),
          Text(
            'Building beautiful cross-platform applications with Flutter.',
            style: TextStyle(fontSize: 14),
          ),
        ],
      ),
    );
  }
}

State Management

Managing state effectively is crucial for building scalable Flutter applications.

State Management Approaches

1. setState (Built-in)

Simple state management for small widgets and local state.

setState(() {
  _counter++;
});

2. Provider (Recommended)

Google's recommended solution for app-wide state management.

// Model
class CounterModel extends ChangeNotifier {
  int _count = 0;
  int get count => _count;

  void increment() {
    _count++;
    notifyListeners();
  }
}

// Usage in widget
Consumer<CounterModel>(
  builder: (context, counter, child) {
    return Text('${counter.count}');
  },
)

3. Other Popular Solutions

Networking & APIs

Flutter provides excellent support for HTTP requests and REST APIs.

Using the http Package

import 'package:http/http.dart' as http;
import 'dart:convert';

// GET Request
Future<List<Post>> fetchPosts() async {
  final response = await http.get(
    Uri.parse('https://api.example.com/posts'),
  );

  if (response.statusCode == 200) {
    List<dynamic> jsonData = json.decode(response.body);
    return jsonData.map((json) => Post.fromJson(json)).toList();
  } else {
    throw Exception('Failed to load posts');
  }
}

// POST Request
Future<Post> createPost(String title, String body) async {
  final response = await http.post(
    Uri.parse('https://api.example.com/posts'),
    headers: {'Content-Type': 'application/json'},
    body: json.encode({
      'title': title,
      'body': body,
    }),
  );

  if (response.statusCode == 201) {
    return Post.fromJson(json.decode(response.body));
  } else {
    throw Exception('Failed to create post');
  }
}

Error Handling

FutureBuilder<List<Post>>(
  future: fetchPosts(),
  builder: (context, snapshot) {
    if (snapshot.hasData) {
      return ListView.builder(
        itemCount: snapshot.data!.length,
        itemBuilder: (context, index) {
          return PostCard(post: snapshot.data![index]);
        },
      );
    } else if (snapshot.hasError) {
      return Text('Error: ${snapshot.error}');
    }
    return CircularProgressIndicator();
  },
)

Data Persistence

Flutter offers several options for storing data locally.

Storage Options

1. Shared Preferences (Key-Value Storage)

import 'package:shared_preferences/shared_preferences.dart';

// Save data
Future<void> saveUserName(String name) async {
  final prefs = await SharedPreferences.getInstance();
  await prefs.setString('userName', name);
}

// Read data
Future<String?> getUserName() async {
  final prefs = await SharedPreferences.getInstance();
  return prefs.getString('userName');
}

2. SQLite (Structured Data)

Use the sqflite package for relational database storage.

3. Hive (NoSQL Database)

Fast, lightweight NoSQL database written in pure Dart.

4. Firebase (Cloud Storage)

Real-time database and cloud storage solution.

Platform Integration

Flutter can access native platform features through platform channels and plugins.

Using Platform Plugins

// Camera access
import 'package:camera/camera.dart';

// Location services
import 'package:geolocator/geolocator.dart';
Position position = await Geolocator.getCurrentPosition();

// Notifications
import 'package:flutter_local_notifications/flutter_local_notifications.dart';

// File picker
import 'package:file_picker/file_picker.dart;

Popular Plugins

Testing

Flutter provides comprehensive testing support at unit, widget, and integration levels.

Test Types

1. Unit Tests

import 'package:test/test.dart';

void main() {
  test('Counter increments', () {
    final counter = Counter();
    counter.increment();
    expect(counter.value, 1);
  });
}

2. Widget Tests

import 'package:flutter_test/flutter_test.dart';

void main() {
  testWidgets('Counter displays correct value', (WidgetTester tester) async {
    await tester.pumpWidget(MyApp());

    expect(find.text('0'), findsOneWidget);

    await tester.tap(find.byIcon(Icons.add));
    await tester.pump();

    expect(find.text('1'), findsOneWidget);
  });
}

3. Integration Tests

Test complete app workflows on real devices or emulators.

Best Practices

Code Organization

Performance

UI/UX

Pro Tip: Use Flutter DevTools for debugging, performance profiling, and inspecting widget trees during development.

Additional Resources

Official Resources

Learning Platforms

Packages & Tools

Community