← Back to Guides

Flutter Development Complete Guide

📖 18 min read | 📅 January 2025 | 🏷️ Mobile Development

Introduction

Flutter is Google's UI toolkit for building natively compiled applications from a single codebase for mobile, web, and desktop. With its reactive framework and rich widget library, Flutter enables fast, beautiful app development.

1. Setup and Installation

# Download Flutter SDK
# https://flutter.dev/docs/get-started/install

# Add to PATH
export PATH="$PATH:`pwd`/flutter/bin"

# Check installation
flutter doctor

# Create new project
flutter create my_app
cd my_app
flutter run

2. Dart Fundamentals

// Variables and types
var name = 'John';
String message = 'Hello';
int age = 30;
double price = 19.99;
bool isActive = true;
List<String> items = ['a', 'b', 'c'];
Map<String, int> scores = {'John': 100};

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

// Optional parameters
void greet(String name, {String? title}) {
  print('Hello ${title ?? ''} $name');
}

// Classes
class User {
  final String name;
  final int age;
  
  User({required this.name, required this.age});
  
  void sayHello() => print('Hi, I\'m $name');
}

// Async/await
Future<String> fetchData() async {
  await Future.delayed(Duration(seconds: 2));
  return 'Data loaded';
}

3. Basic Widgets

import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(primarySwatch: Colors.blue),
      home: HomeScreen(),
    );
  }
}

class HomeScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('Home')),
      body: Column(
        children: [
          Text('Hello Flutter', 
            style: TextStyle(fontSize: 24)
          ),
          ElevatedButton(
            onPressed: () => print('Pressed'),
            child: Text('Click Me'),
          ),
          Image.network('https://example.com/image.png'),
          Container(
            padding: EdgeInsets.all(16),
            decoration: BoxDecoration(
              color: Colors.blue,
              borderRadius: BorderRadius.circular(8),
            ),
            child: Text('Container'),
          ),
        ],
      ),
    );
  }
}

4. Layouts

// Column & Row
Column(
  mainAxisAlignment: MainAxisAlignment.center,
  crossAxisAlignment: CrossAxisAlignment.start,
  children: [
    Text('Item 1'),
    Text('Item 2'),
  ],
)

// Stack (overlapping widgets)
Stack(
  children: [
    Image.network('background.jpg'),
    Positioned(
      top: 20,
      left: 20,
      child: Text('Overlay Text'),
    ),
  ],
)

// ListView
ListView.builder(
  itemCount: items.length,
  itemBuilder: (context, index) {
    return ListTile(
      title: Text(items[index]),
      onTap: () => handleTap(index),
    );
  },
)

// GridView
GridView.count(
  crossAxisCount: 2,
  children: List.generate(10, (index) {
    return Card(child: Center(child: Text('Item $index')));
  }),
)

5. State Management

// StatefulWidget
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'),
        ),
      ],
    );
  }
}

// Provider pattern
# pubspec.yaml
dependencies:
  provider: ^6.0.0

import 'package:provider/provider.dart';

class CounterModel extends ChangeNotifier {
  int _count = 0;
  int get count => _count;
  
  void increment() {
    _count++;
    notifyListeners();
  }
}

// Usage
ChangeNotifierProvider(
  create: (context) => CounterModel(),
  child: MyApp(),
)

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

6. Navigation

// Basic navigation
Navigator.push(
  context,
  MaterialPageRoute(builder: (context) => SecondScreen()),
);

Navigator.pop(context);

// Named routes
MaterialApp(
  routes: {
    '/': (context) => HomeScreen(),
    '/details': (context) => DetailsScreen(),
  },
)

Navigator.pushNamed(context, '/details', arguments: {'id': 123});

// Get arguments
final args = ModalRoute.of(context)!.settings.arguments as Map;

// Navigator 2.0 (go_router)
# pubspec.yaml
dependencies:
  go_router: ^13.0.0

final router = GoRouter(
  routes: [
    GoRoute(
      path: '/',
      builder: (context, state) => HomeScreen(),
    ),
    GoRoute(
      path: '/details/:id',
      builder: (context, state) {
        final id = state.pathParameters['id'];
        return DetailsScreen(id: id);
      },
    ),
  ],
);

context.go('/details/123');

7. API Integration

# pubspec.yaml
dependencies:
  http: ^1.1.0

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

class ApiService {
  static const baseUrl = 'https://api.example.com';
  
  Future<List<User>> getUsers() async {
    final response = await http.get(Uri.parse('$baseUrl/users'));
    
    if (response.statusCode == 200) {
      List data = json.decode(response.body);
      return data.map((json) => User.fromJson(json)).toList();
    }
    throw Exception('Failed to load users');
  }
  
  Future<void> createUser(User user) async {
    await http.post(
      Uri.parse('$baseUrl/users'),
      headers: {'Content-Type': 'application/json'},
      body: json.encode(user.toJson()),
    );
  }
}

// Model with JSON serialization
class User {
  final int id;
  final String name;
  
  User({required this.id, required this.name});
  
  factory User.fromJson(Map<String, dynamic> json) {
    return User(id: json['id'], name: json['name']);
  }
  
  Map<String, dynamic> toJson() => {'id': id, 'name': name};
}

8. Local Storage

# pubspec.yaml
dependencies:
  shared_preferences: ^2.2.0
  sqflite: ^2.3.0

// SharedPreferences
import 'package:shared_preferences/shared_preferences.dart';

final prefs = await SharedPreferences.getInstance();
await prefs.setString('username', 'john');
final username = prefs.getString('username');

// SQLite
import 'package:sqflite/sqflite.dart';

class DatabaseHelper {
  static Database? _database;
  
  Future<Database> get database async {
    if (_database != null) return _database!;
    _database = await initDatabase();
    return _database!;
  }
  
  Future<Database> initDatabase() async {
    return await openDatabase(
      'app.db',
      version: 1,
      onCreate: (db, version) {
        return db.execute(
          'CREATE TABLE users(id INTEGER PRIMARY KEY, name TEXT)',
        );
      },
    );
  }
  
  Future<void> insertUser(User user) async {
    final db = await database;
    await db.insert('users', user.toMap());
  }
  
  Future<List<User>> getUsers() async {
    final db = await database;
    final List<Map<String, dynamic>> maps = await db.query('users');
    return List.generate(maps.length, (i) => User.fromMap(maps[i]));
  }
}

9. Animations

class AnimatedBox extends StatefulWidget {
  @override
  _AnimatedBoxState createState() => _AnimatedBoxState();
}

class _AnimatedBoxState extends State<AnimatedBox>
    with SingleTickerProviderStateMixin {
  late AnimationController _controller;
  late Animation<double> _animation;
  
  @override
  void initState() {
    super.initState();
    _controller = AnimationController(
      duration: Duration(seconds: 2),
      vsync: this,
    );
    _animation = Tween<double>(begin: 0, end: 300).animate(_controller);
    _controller.forward();
  }
  
  @override
  Widget build(BuildContext context) {
    return AnimatedBuilder(
      animation: _animation,
      builder: (context, child) {
        return Container(
          width: _animation.value,
          height: _animation.value,
          color: Colors.blue,
        );
      },
    );
  }
  
  @override
  void dispose() {
    _controller.dispose();
    super.dispose();
  }
}

10. Testing

# pubspec.yaml
dev_dependencies:
  flutter_test:
    sdk: flutter

// Unit test
import 'package:flutter_test/flutter_test.dart';

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

// Widget test
testWidgets('Button tap increments counter', (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);
});
💡 Best Practices:

Conclusion

Flutter provides a powerful framework for building beautiful, high-performance cross-platform applications. Master these concepts to create professional mobile apps with excellent user experiences.