Skip to content
Learni
View all tutorials
Développement Mobile

Comment créer votre première app Flutter en 2026

Introduction

Flutter, framework open-source de Google, révolutionne le développement mobile en 2026 grâce à son rendu natif ultra-performant et son paradigme declarative UI. Contrairement aux frameworks hybrides comme React Native, Flutter compile en code natif ARM, offrant des performances identiques à Swift ou Kotlin, tout en utilisant un seul codebase pour iOS, Android, web et desktop.

Pourquoi l'adopter maintenant ? En 2026, 70% des apps Fortune 500 utilisent Flutter pour sa rapidité de développement (hot reload en <1s) et son widget kit riche (Material 3, Cupertino). Ce tutoriel débutant vous guide pas à pas pour créer une app Counter évolutive vers une Todo List, avec 100% de code copier-collable. À la fin, vous maîtriserez les bases : widgets stateless/stateful, gestion d'état simple, navigation et déploiement. Prêt à booster votre carrière dev mobile ? (128 mots)

Prérequis

  • Ordinateur avec macOS, Windows ou Linux (8 Go RAM min.)
  • Flutter SDK version 3.24+ (stable 2026)
  • Android Studio (pour émulateur Android) ou Xcode (macOS pour iOS)
  • VS Code avec extensions Flutter et Dart
  • Connaissances basiques en programmation (pas de Dart requis, on apprend en chemin)

Installer et vérifier Flutter

terminal
git clone https://github.com/flutter/flutter.git -b stable

export PATH="$PATH:`pwd`/flutter/bin"
flutter precache
flutter doctor -v

Ces commandes clonent le SDK Flutter stable, l'ajoutent au PATH et vérifient l'installation. flutter doctor liste les outils manquants (ex: Android SDK). Évitez les versions beta pour un débutant ; relancez votre terminal après export PATH.

Créer votre premier projet

Analogie : Créer un projet Flutter est comme initialiser un nouveau dossier Git, mais avec un squelette d'app prêt à coder. Cela génère lib/main.dart (point d'entrée), pubspec.yaml (dépendances) et les configs iOS/Android.

Générer le projet

terminal
flutter create ma_premiere_app
cd ma_premiere_app
flutter pub get

flutter create scaffold un projet complet avec Material Design par défaut. pub get résout les dépendances. Lancez flutter run pour tester sur émulateur ; si erreur, vérifiez flutter doctor.

App de base : main.dart

lib/main.dart
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: 'Ma Première App',
      theme: ThemeData(primarySwatch: Colors.blue),
      home: const MyHomePage(title: 'Accueil'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({super.key, required this.title});

  final String title;

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  int _counter = 0;

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text(widget.title)),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            const Text('Vous avez appuyé tant de fois:'),
            Text(
              '$_counter',
              style: Theme.of(context).textTheme.headlineMedium,
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _incrementCounter,
        tooltip: 'Increment',
        child: const Icon(Icons.add),
      ),
    );
  }
}

Ce code crée une app Counter complète : runApp lance l'app, MaterialApp gère le thème/routing, StatefulWidget met à jour l'UI via setState. Copiez-collez dans lib/main.dart, puis flutter run. Piège : Oubliez const pour les performances ; key évite les rebuilds inutiles.

Comprendre les widgets

Flutter est basé sur des widgets immutables : tout est un widget (UI + logique). Stateless pour statique (ex: icônes), Stateful pour dynamique (ex: compteur). L'arbre de widgets se reconstruit à chaque setState, comme un arbre DOM réactif mais plus rapide.

Ajouter une ListView

lib/main.dart
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: 'Ma App ListView',
      theme: ThemeData(primarySwatch: Colors.green),
      home: const MyHomePage(),
    );
  }
}

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Ma ListView')),
      body: ListView.builder(
        itemCount: 20,
        itemBuilder: (context, index) {
          return ListTile(
            leading: const Icon(Icons.star),
            title: Text('Item $index'),
            subtitle: Text('Sous-titre $index'),
            trailing: const Icon(Icons.arrow_forward_ios),
          );
        },
      ),
    );
  }
}

Remplacez le body par ListView.builder pour une liste infinie optimisée (lazy loading). itemBuilder génère dynamiquement ; itemCount limite. Idéal pour les listes longues. Évitez ListView fixe pour les perfs mobiles.

Todo List avec état

lib/main.dart
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: 'Todo App',
      theme: ThemeData(primarySwatch: Colors.orange),
      home: const TodoListScreen(),
    );
  }
}

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

  @override
  State<TodoListScreen> createState() => _TodoListScreenState();
}

class _TodoListScreenState extends State<TodoListScreen> {
  final List<String> _todos = [];
  final TextEditingController _controller = TextEditingController();

  void _addTodo() {
    if (_controller.text.isNotEmpty) {
      setState(() {
        _todos.add(_controller.text);
        _controller.clear();
      });
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Mes Todos')),
      body: Column(
        children: [
          Padding(
            padding: const EdgeInsets.all(16.0),
            child: Row(
              children: [
                Expanded(
                  child: TextField(
                    controller: _controller,
                    decoration: const InputDecoration(hintText: 'Nouvelle todo'),
                  ),
                ),
                IconButton(
                  onPressed: _addTodo,
                  icon: const Icon(Icons.add),
                ),
              ],
            ),
          ),
          Expanded(
            child: ListView.builder(
              itemCount: _todos.length,
              itemBuilder: (context, index) => ListTile(
                title: Text(_todos[index]),
                trailing: IconButton(
                  icon: const Icon(Icons.delete),
                  onPressed: () => setState(() => _todos.removeAt(index)),
                ),
              ),
            ),
          ),
        ],
      ),
    );
  }

  @override
  void dispose() {
    _controller.dispose();
    super.dispose();
  }
}

Cette Todo App gère l'état avec List, TextEditingController pour input, et dispose pour cleanup. setState trigger rebuilds ciblés. Ajoute/supprime dynamiquement. Piège : Oublier dispose fuit la mémoire ; utilisez Expanded pour scroll fluide.

Lancer l'app

terminal
flutter run -d chrome  # Pour web
# ou
flutter run  # Pour émulateur connecté

# Hot reload: tapez 'r'
# Hot restart: 'R'

flutter run compile et lance sur device/émulateur/web. -d chrome pour test rapide web. Hot reload préserve l'état. Vérifiez flutter devices pour lister les cibles.

Bonnes pratiques

  • Hot Reload : Sauvegardez (Ctrl+S) pour itérer vite, mais Hot Restart pour changements d'état.
  • Utilisez const partout pour optimiser les rebuilds.
  • State Management : SetState pour débutants ; passez à Provider/Riverpod pour apps complexes.
  • Testez sur vrais devices : émulateurs lent pour animations.
  • Pubspec.yaml : Ajoutez deps comme http: ^1.2.0 pour API, puis flutter pub get.

Erreurs courantes à éviter

  • Indentation/{} manquants : Dart est strict ; VS Code auto-format (Ctrl+Shift+I).
  • Pas de setState : UI ne se met pas à jour (classique pour débutants).
  • Controller non disposé : Fuites mémoire sur Android/iOS.
  • flutter clean oublié : Après changements pubspec, tapez flutter clean && flutter pub get.

Pour aller plus loin