Créez votre première app mobile avec Flutter en 2026 - Tutoriel complet débutant

📅 20 mai 2026
📁 Tutoriels
Tutoriel
Créez votre première app mobile avec Flutter en 2026 | Mat-Univer.tech
🦋 Flutter 3.41 — Version 2026

Créez votre première app mobile avec Flutter

De zéro à une application fonctionnelle sur Android et iOS — le guide complet en français pour débutants.

✍️ Matteo 📅 Mai 2026 ⏱️ 15 min de lecture

Introduction : Pourquoi Flutter en 2026 ?

Vous voulez créer une application mobile mais vous ne savez pas par où commencer ? Vous avez entendu parler de Flutter mais ça reste flou ? Ce guide est fait pour vous.

Flutter est un framework open source créé par Google qui permet de développer des applications pour 6 plateformes (iOS, Android, Web, Windows, macOS, Linux) avec un seul code. En 2026, il est devenu le framework cross-platform le plus utilisé au monde, et pour de bonnes raisons.

Hot ReloadVoyez vos changements instantanément sans recompiler — un gain de temps énorme.
🎨
UI pixel-perfectL'interface est identique sur iOS et Android. Pas de mauvaises surprises.
🚀
Impeller EngineLe moteur de rendu natif élimine totalement le "jank" (lag d'animations).
🤖
AI Toolkit v1.0Widgets IA pré-construits pour intégrer l'IA dans vos apps facilement.
📦
1 code = 6 plateformesBudget divisé par 3 comparé au développement natif séparé.
🏢
Production-readyUtilisé par Google, BMW, Alibaba, eBay, Toyota et des milliers de startups.

Flutter en est aujourd'hui à la version 3.41.5 (mai 2026), avec le moteur Impeller stable, le support complet d'iOS 26 et Android 17, et la syntaxe Dart dot shorthands qui rend le code plus propre que jamais.

Flutter vs React Native vs Natif

Avant de commencer, comparons les options qui s'offrent à vous :

CritèreFlutterReact NativeNatif
LangageDartJavaScriptSwift / Kotlin
Plateformes6 (mobile+web+desktop)Mobile + Web1 par OS
PerformanceNatif-like (Impeller)Bridge JavaScriptMaximum
UI cohérence100% identiqueVarie par OSDifférent
Hot ReloadSub-secondeFast RefreshNon / Lent
Temps de dev MVP12-16 semaines14-20 semaines20-28 semaines
Coût relatif1x1.3x2-3x

Pour 90% des projets, Flutter offre le meilleur rapport qualité/prix/temps. Les seules exceptions : si votre équipe est déjà experte React/JavaScript (React Native), ou si vous avez besoin d'un accès jour-1 aux dernières APIs hardware (natif).

Ce dont vous avez besoin

Matériel requis

  • Ordinateur : Windows 10+, macOS 12+, ou Ubuntu 22.04+
  • RAM : 8 GB minimum (16 GB recommandé)
  • Disque : 10 GB d'espace libre
  • Pour tester sur iOS : Un Mac est obligatoire (Apple l'exige)

Connaissances recommandées

  • Notions de base en programmation (variables, boucles, fonctions)
  • Connaissance d'un langage orienté objet est un plus (Java, Python, C#...)
  • Pas besoin de connaître Dart — on l'apprend ensemble dans ce tutoriel

Installation complète

Étape 1 : Installer Flutter SDK

Sur Linux (Ubuntu/Debian)

# Installer les dépendances
sudo apt update
sudo apt install -y curl git unzip xz-utils zip

# Télécharger Flutter
cd ~
git clone https://github.com/flutter/flutter.git -b stable

# Ajouter au PATH
echo 'export PATH="$HOME/flutter/bin:$PATH"' >> ~/.bashrc
source ~/.bashrc

# Vérifier l'installation
flutter --version

Sur Windows

  1. Téléchargez Flutter SDK depuis flutter.dev
  2. Extrayez dans C:\flutter\
  3. Ajoutez C:\flutter\bin à votre variable PATH
  4. Ouvrez PowerShell et tapez flutter --version

Sur macOS

# Avec Homebrew (recommandé)
brew install flutter

# Ou manuellement
cd ~
git clone https://github.com/flutter/flutter.git -b stable
echo 'export PATH="$HOME/flutter/bin:$PATH"' >> ~/.zshrc
source ~/.zshrc

Étape 2 : Configurer un éditeur

Installez VS Code (gratuit) ou Android Studio, puis ajoutez les extensions :

  • Flutter (extension officielle)
  • Dart (extension officielle)

Étape 3 : Vérifier l'installation

flutter doctor

Cette commande vérifie que tout est correctement installé. Corrigez les éventuels problèmes signalés avant de continuer.

💡 flutter doctor vous dira exactement ce qui manque. Suivez ses instructions — c'est le meilleur guide de dépannage.

Étape 4 : Créer votre premier projet

# Créer un nouveau projet
flutter create mon_app

# Ouvrir le projet
cd mon_app

# Lancer l'app (assurez-vous d'avoir un émulateur ou un appareil connecté)
flutter run

Si tout fonctionne, vous verrez l'app de démonstration Flutter avec un compteur. Félicitations, votre environnement est prêt !

Les bases de Dart en 10 minutes

Dart est le langage utilisé par Flutter. Si vous connaissez Java, JavaScript ou Python, vous serez en terrain familier. Voici l'essentiel.

Variables et types

// Types explicites
String nom = 'Matteo';
int age = 25;
double pi = 3.14;
bool estDev = true;
List<String> langages = ['Dart', 'Python', 'PHP'];

// Inférence de type (recommandé)
var ville = 'Port-Louis';        // Dart devine que c'est un String
final pays = 'Île Maurice';      // Constante (ne peut pas être réassignée)
const gravite = 9.81;            // Constante de compilation

Fonctions

// Fonction classique
String saluer(String nom) {
  return 'Bonjour, $nom !';
}

// Fonction fléchée (une ligne)
String saluer2(String nom) => 'Bonjour, $nom !';

// Paramètres optionnels nommés
void creerUtilisateur({
  required String nom,
  int age = 18,
  String? email,     // Nullable (peut être null)
}) {
  print('$nom a $age ans');
}

Classes

class Utilisateur {
  final String nom;
  final int age;

  // Constructeur court (Dart style)
  Utilisateur({required this.nom, required this.age});

  // Méthode
  String sePresenter() => 'Je suis $nom, $age ans';
}

// Utilisation
final user = Utilisateur(nom: 'Matteo', age: 25);
print(user.sePresenter());

Null Safety

// Dart utilise le "sound null safety"
// Une variable ne peut PAS être null sauf si vous le dites explicitement

String nom = 'Matteo';      // Ne peut JAMAIS être null
String? email;               // Peut être null (noté avec ?)

// Vérification
if (email != null) {
  print(email.length);       // Safe
}

// Opérateur ?? (valeur par défaut)
String affichage = email ?? 'Pas d\'email';

// Opérateur ?. (appel conditionnel)
int? longueur = email?.length;  // null si email est null
💡 Le null safety de Dart attrape les erreurs à la compilation, pas au runtime. C'est un énorme avantage par rapport à JavaScript où les null pointer exceptions arrivent en production.

Nouveauté 2026 : Dot Shorthands

// Avant
Column(
  mainAxisAlignment: MainAxisAlignment.center,
  crossAxisAlignment: CrossAxisAlignment.start,
)

// Maintenant (Dart 3.10+)
Column(
  mainAxisAlignment: .center,
  crossAxisAlignment: .start,
)

Cette syntaxe inspirée de Swift rend le code Flutter beaucoup plus lisible.

Comprendre les Widgets

En Flutter, tout est un Widget. Un bouton, un texte, une image, une page entière — tout est un widget. Il existe deux types :

📦
StatelessWidgetNe change jamais après sa création. Exemple : un texte fixe, une icône, un logo.
🔄
StatefulWidgetPeut changer au fil du temps. Exemple : un compteur, un formulaire, une liste dynamique.

StatelessWidget — Exemple

class CarteProfile extends StatelessWidget {
  final String nom;
  final String role;

  const CarteProfile({
    super.key,
    required this.nom,
    required this.role,
  });

  @override
  Widget build(BuildContext context) {
    return Container(
      padding: EdgeInsets.all(16),
      decoration: BoxDecoration(
        color: Colors.grey[900],
        borderRadius: BorderRadius.circular(12),
      ),
      child: Column(
        children: [
          CircleAvatar(radius: 40, child: Text(nom[0])),
          SizedBox(height: 12),
          Text(nom, style: TextStyle(
            fontSize: 20,
            fontWeight: FontWeight.bold,
            color: Colors.white,
          )),
          Text(role, style: TextStyle(color: Colors.grey)),
        ],
      ),
    );
  }
}

StatefulWidget — Exemple

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

  @override
  State<Compteur> createState() => _CompteurState();
}

class _CompteurState extends State<Compteur> {
  int _count = 0;

  @override
  Widget build(BuildContext context) {
    return Column(
      mainAxisAlignment: .center,
      children: [
        Text(
          '$_count',
          style: TextStyle(fontSize: 48, fontWeight: FontWeight.bold),
        ),
        SizedBox(height: 16),
        ElevatedButton(
          onPressed: () => setState(() => _count++),
          child: Text('Incrémenter'),
        ),
      ],
    );
  }
}

Les widgets de layout essentiels

WidgetRôleAnalogie HTML
ColumnEmpile les enfants verticalementdiv avec flex-direction: column
RowAligne les enfants horizontalementdiv avec flex-direction: row
ContainerBoîte avec padding, margin, décorationdiv avec du CSS
ScaffoldStructure de page (appbar, body, fab)body + header + main
ListViewListe scrollablediv avec overflow: scroll
StackSuperpose les enfantsposition: relative/absolute
PaddingAjoute de l'espace intérieurpadding en CSS
SizedBoxEspace fixe entre les widgetsmargin ou gap

Construire l'app pas à pas

Construisons une application concrète : une app de tâches (Todo List) avec ajout, suppression et persistance locale.

Structure du projet

lib/
├── main.dart              # Point d'entrée
├── models/
│   └── task.dart          # Modèle de données
├── screens/
│   └── home_screen.dart   # Page principale
└── widgets/
    └── task_tile.dart     # Widget d'une tâche

1. Le modèle de données

// lib/models/task.dart
class Task {
  final String id;
  final String title;
  bool isDone;

  Task({
    required this.id,
    required this.title,
    this.isDone = false,
  });
}

2. Le widget d'une tâche

// lib/widgets/task_tile.dart
import 'package:flutter/material.dart';
import '../models/task.dart';

class TaskTile extends StatelessWidget {
  final Task task;
  final VoidCallback onToggle;
  final VoidCallback onDelete;

  const TaskTile({
    super.key,
    required this.task,
    required this.onToggle,
    required this.onDelete,
  });

  @override
  Widget build(BuildContext context) {
    return ListTile(
      leading: Checkbox(
        value: task.isDone,
        onChanged: (_) => onToggle(),
      ),
      title: Text(
        task.title,
        style: TextStyle(
          decoration: task.isDone
              ? TextDecoration.lineThrough
              : TextDecoration.none,
          color: task.isDone ? Colors.grey : Colors.white,
        ),
      ),
      trailing: IconButton(
        icon: Icon(Icons.delete, color: Colors.red[300]),
        onPressed: onDelete,
      ),
    );
  }
}

3. L'écran principal

// lib/screens/home_screen.dart
import 'package:flutter/material.dart';
import '../models/task.dart';
import '../widgets/task_tile.dart';

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

  @override
  State<HomeScreen> createState() => _HomeScreenState();
}

class _HomeScreenState extends State<HomeScreen> {
  final List<Task> _tasks = [];
  final _controller = TextEditingController();

  void _addTask() {
    if (_controller.text.trim().isEmpty) return;
    setState(() {
      _tasks.add(Task(
        id: DateTime.now().toString(),
        title: _controller.text.trim(),
      ));
      _controller.clear();
    });
  }

  void _toggleTask(int index) {
    setState(() => _tasks[index].isDone = !_tasks[index].isDone);
  }

  void _deleteTask(int index) {
    setState(() => _tasks.removeAt(index));
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Mes Tâches'),
        centerTitle: true,
      ),
      body: Column(
        children: [
          // Barre d'ajout
          Padding(
            padding: EdgeInsets.all(16),
            child: Row(
              children: [
                Expanded(
                  child: TextField(
                    controller: _controller,
                    decoration: InputDecoration(
                      hintText: 'Nouvelle tâche...',
                      border: OutlineInputBorder(
                        borderRadius: BorderRadius.circular(12),
                      ),
                    ),
                    onSubmitted: (_) => _addTask(),
                  ),
                ),
                SizedBox(width: 12),
                FloatingActionButton(
                  onPressed: _addTask,
                  child: Icon(Icons.add),
                ),
              ],
            ),
          ),

          // Liste des tâches
          Expanded(
            child: _tasks.isEmpty
                ? Center(child: Text('Aucune tâche'))
                : ListView.builder(
                    itemCount: _tasks.length,
                    itemBuilder: (context, index) => TaskTile(
                      task: _tasks[index],
                      onToggle: () => _toggleTask(index),
                      onDelete: () => _deleteTask(index),
                    ),
                  ),
          ),
        ],
      ),
    );
  }
}

4. Le point d'entrée

// lib/main.dart
import 'package:flutter/material.dart';
import 'screens/home_screen.dart';

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

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Todo App',
      debugShowCheckedModeBanner: false,
      theme: ThemeData.dark(useMaterial3: true).copyWith(
        colorScheme: ColorScheme.dark(
          primary: Colors.cyanAccent,
          surface: Color(0xFF121212),
        ),
      ),
      home: HomeScreen(),
    );
  }
}
🎉 Lancez flutter run et vous avez une Todo app complète fonctionnelle ! Ajoutez des tâches, cochez-les, supprimez-les.

Gérer l'état (State Management)

Pour des apps simples, setState suffit. Mais quand l'app grandit (plusieurs pages qui partagent des données), vous avez besoin d'une solution plus robuste.

SolutionComplexitéIdéal pour
setStateSimpleApps de 1-2 pages
ProviderSimpleApps moyennes, débutants
RiverpodMoyenApps complexes (recommandé en 2026)
Bloc / CubitAvancéApps enterprise, équipes

En 2026, Riverpod est devenu le standard de facto. Il est type-safe, testable, et bien documenté.

Utilisez go_router, le package de navigation officiel recommandé par Google :

// pubspec.yaml
dependencies:
  go_router: ^14.0.0
// Configuration des routes
final router = GoRouter(
  routes: [
    GoRoute(
      path: '/',
      builder: (context, state) => HomeScreen(),
    ),
    GoRoute(
      path: '/details/:id',
      builder: (context, state) {
        final id = state.pathParameters['id']!;
        return DetailsScreen(taskId: id);
      },
    ),
  ],
);

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

Connecter une API REST

Utilisez le package dio pour les appels HTTP :

// pubspec.yaml
dependencies:
  dio: ^5.4.0
import 'package:dio/dio.dart';

class ApiService {
  final _dio = Dio(BaseOptions(
    baseUrl: 'https://jsonplaceholder.typicode.com',
  ));

  Future<List<dynamic>> getTodos() async {
    final response = await _dio.get('/todos');
    return response.data;
  }

  Future<void> createTodo(String title) async {
    await _dio.post('/todos', data: {
      'title': title,
      'completed': false,
    });
  }
}

Les packages essentiels en 2026

PackageRôleCommande
riverpodState managementflutter pub add flutter_riverpod
go_routerNavigation déclarativeflutter pub add go_router
dioHTTP / appels APIflutter pub add dio
hiveBase de données locale rapideflutter pub add hive
freezedData classes immuablesflutter pub add freezed_annotation
cached_network_imageImages avec cacheflutter pub add cached_network_image
easy_localizationTraductions FR/ENflutter pub add easy_localization
flutter_animateAnimations simplesflutter pub add flutter_animate

Compiler et déployer

Générer l'APK Android

# APK de debug (pour tester)
flutter build apk --debug

# APK de release (pour publier)
flutter build apk --release

# App Bundle (recommandé pour le Play Store)
flutter build appbundle --release

L'APK se trouve dans build/app/outputs/flutter-apk/

Générer l'app iOS

# Nécessite un Mac avec Xcode
flutter build ios --release

Générer l'app Web

flutter build web --release
# Le dossier build/web/ peut être déployé sur n'importe quel hébergeur
⚠️ Pour publier sur le Google Play Store, vous devez signer votre APK avec une clé de release. Consultez la documentation officielle pour les étapes détaillées.

Erreurs courantes et solutions

"Gradle build failed" (Android)

  • Vérifiez que minSdkVersion est à 21+ dans android/app/build.gradle
  • Lancez flutter clean puis flutter pub get
  • Vérifiez votre version de Java (Java 17 recommandé)

"Widget overflow" (écran jaune/noir)

  • Encapsulez les listes dans Expanded ou Flexible
  • Utilisez SingleChildScrollView pour les pages qui dépassent l'écran
  • Vérifiez les Column à l'intérieur de Column (problème classique)

"setState() called after dispose()"

  • Vérifiez que le widget est toujours monté : if (mounted) setState(...);
  • Annulez les timers et subscriptions dans dispose()

Hot Reload ne fonctionne plus

  • Arrêtez l'app et relancez avec flutter run
  • Certains changements (ajout de plugins, changements natifs) nécessitent un hot restart (R majuscule dans le terminal)

Pour aller plus loin

Vous avez maintenant les bases solides pour construire des applications Flutter. Voici la suite du parcours :

📚
Riverpod en profondeurApprenez le state management moderne pour des apps complexes et maintenables.
🎨
Animations avancéesMaîtrisez AnimationController, Hero transitions et les shaders custom avec Impeller.
🔥
Firebase / SupabaseAjoutez un backend : auth, base de données temps réel, notifications push.
🤖
Flutter AI ToolkitIntégrez des fonctionnalités IA (chat, génération de texte, speech-to-text) dans vos apps.
🧪
TestsUnit tests, widget tests, integration tests — rendez votre code fiable et maintenable.
🌐
Flutter Web & DesktopPortez votre app mobile sur le web et le desktop avec le même code.

Ressources recommandées

Conclusion

Flutter en 2026 n'est plus un framework expérimental — c'est un outil de production utilisé par des entreprises du Fortune 500. Avec Impeller, le AI Toolkit, et l'écosystème mature de packages, c'est le meilleur moment pour commencer.

Ce que vous avez appris dans ce tutoriel : les bases de Dart et du null safety, le système de widgets (Stateless et Stateful), la construction d'une app complète (Todo List), le state management et la navigation, les appels API et les packages essentiels, et la compilation et le déploiement.

La prochaine étape ? Construisez quelque chose. Le meilleur moyen d'apprendre Flutter, c'est de coder. Prenez une idée simple et réalisez-la. Votre première app ne sera pas parfaite, et c'est normal.

Retrouvez plus de tutoriels, projets et ressources sur mat-univer.tech. Et n'hésitez pas à partager vos créations Flutter dans les commentaires !

M
Matteo — CodexMatteo
Développeur & créateur de contenu tech — Île Maurice