Au cours précédent, nous avons créé notre premier projet Flutter. Il est très simple : il ne contient qu’un bouton qui incrémente un nombre à chaque clic. Voici la structure des dossiers de ce projet.
Arborescence du projet

Vous voyez de nombreux dossiers et fichiers : android, web, windows, lib, test, etc. Où se trouve le code source à écrire ? Dans android ? Dans windows ? En réalité non, il est dans le dossier lib. Ouvrez lib, vous verrez un fichier main.dart.

Ce dossier lib contiendra tout votre code source à l’avenir. Vous écrivez en Dart, pas en Java ni en C++. Flutter utilise le langage Dart. Pourquoi existe-t-il alors des dossiers android, web, windows et autres à la racine ?
C’est facile à comprendre : Flutter peut se compiler en applications multi-plateformes grâce à ces dossiers.
Flutter est un framework basé sur le principe un seul code Dart, exécutable sur plusieurs plateformes. Le dossier lib contient le code métier commun multi-plateforme que vous développez ; tandis que les dossiers android / windows / web / macos / linux sont des projets hôtes natifs de chaque plateforme, chargés d’intégrer le moteur de rendu Flutter au système correspondant pour l’exécution.
1. Dossier android
C’est le projet natif de la plateforme Android
Il fournit le conteneur d’exécution de l’application Android et héberge le moteur de rendu Flutter. Tous les paramètres bas niveau liés à Android se configurent ici : permissions de l’app, icônes, nom du package, etc. Vous pouvez donc paramétrer des éléments spécifiques à Android et appeler les API natives du système (caméra, Bluetooth, notifications, géolocalisation, etc.)
2. Dossier windows
Il s’agit du projet natif pour ordinateur de bureau Windows
C’est un projet natif C++ Win32 qui crée des fenêtres Windows et initialise le moteur graphique Skia. Skia est la bibliothèque graphique de Google, utilisée par Flutter pour dessiner les fenêtres et tous les composants des applications de bureau.
Le dossier windows regroupe les configurations bas niveau du logiciel de bureau Windows : taille de fenêtre, barre de titre, icônes, zone de notification (l’icône en bas à droite de Windows).
Vous pouvez ensuite empaqueter le projet en exe ou msix pour le publier sur le Microsoft Store.
3. Dossier web
Projet de pages web statiques (HTML/JS/CSS) qui propose le point d’entrée web index.html. Votre code Dart est compilé en ressources web finales.
On y configure le titre de la page, les icônes, les ressources statiques et les routes. La compilation génère des fichiers HTML/CSS/JS prêts à héberger sur un serveur et à ouvrir dans un navigateur.
Autres dossiers
Nous n’avons pas utilisé iOS, macOS et Linux ici car nous n’avons pas coché ces options lors de la création du projet, ces dossiers n’apparaissent donc pas. Leur fonctionnement reste identique.
ios : Projet Xcode natif Apple iOS, pour empaqueter des fichiers ipa et publier sur iPhone
macos : Projet natif Cocoa pour bureau macOS, client pour ordinateurs Mac
linux : Projet de bureau Linux basé sur GTK
Dans le coin supérieur droit d’Android Studio, vous sélectionnez différentes plateformes pour compiler des versions distinctes de l’application. Vous pouvez aussi utiliser directement la ligne de commande ; en réalité, quand vous choisissez une plateforme et cliquez sur le triangle vert dans Android Studio, des commandes Flutter s’exécutent en arrière-plan.
# Lancer Android, lit les configurations du dossier android
flutter run -d android
# Lancer le bureau Windows, lit le projet C++ du dossier windows
flutter run -d windows
# Lancer la version web, lit le html du dossier web
flutter run -d chromeLangage du code : PHP (php)

Ouvrez le fichier runner / main.cpp dans le dossier windows
#include <flutter/dart_project.h>
#include <flutter/flutter_view_controller.h>
#include <windows.h>
#include "flutter_window.h"
#include "utils.h"
int APIENTRY wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev,
_In_ wchar_t *command_line, _In_ int show_command) {
// Attach to console when present (e.g., 'flutter run') or create a
// new console when running with a debugger.
if (!::AttachConsole(ATTACH_PARENT_PROCESS) && ::IsDebuggerPresent()) {
CreateAndAttachConsole();
}
// Initialize COM, so that it is available for use in the library and/or
// plugins.
::CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED);
flutter::DartProject project(L"data");
std::vector<std::string> command_line_arguments =
GetCommandLineArguments();
project.set_dart_entrypoint_arguments(std::move(command_line_arguments));
FlutterWindow window(project);
Win32Window::Point origin(10, 10);
Win32Window::Size size(1280, 720);
if (!window.Create(L"myproject", origin, size)) {
return EXIT_FAILURE;
}
window.SetQuitOnClose(true);
::MSG msg;
while (::GetMessage(&msg, nullptr, 0, 0)) {
::TranslateMessage(&msg);
::DispatchMessage(&msg);
}
::CoUninitialize();
return EXIT_SUCCESS;
}
Langage du code : PHP (php)
Si vous compilez pour Windows Desktop, ce main.cpp est le véritable point d’entrée du programme : ce fichier C++ s’exécute en premier, puis le contrôle passe à votre lib/main.dart.
De même, en ouvrant le dossier android, vous verrez une structure quasi identique aux projets Android développés en Kotlin ou Java.

On y trouve aussi le dossier src, le fichier AndroidManifest.xml, MainActivity et d’autres éléments familiers pour qui développe des apps Android. En réalité, le lancement d’une app Android sous Flutter débute dans ce dossier android.
De la même façon, ouvrez le dossier web et vous trouverez le point d’entrée web index.html

Fichiers Dart
Le fichier main.dart dans lib sera le cœur de votre développement futur. Vous pouvez créer des sous-dossiers et ajouter d’autres fichiers Dart dans lib.
Ouvrez main.dart
// Importer la bibliothèque de composants Material
import 'package:flutter/material.dart';
// Fonction point d'entrée du programme
void main() {
runApp(const MyApp());
}
// Composant racine de l'application (sans état)
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
// Configuration globale du thème
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
),
// Page d'accueil
home: const MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
// Page d'accueil (composant avec état)
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key, required this.title});
// Paramètre titre de la page
final String title;
@override
State<MyHomePage> createState() => _MyHomePageState();
}
// Classe de gestion d'état de la page d'accueil
class _MyHomePageState extends State<MyHomePage> {
// Variable compteur
int _counter = 0;
// Méthode d'incrémentation du compteur
void _incrementCounter() {
setState(() {
_counter++;
});
}
@override
Widget build(BuildContext context) {
// Modèle de mise en page de base pour une page
return Scaffold(
// Barre de navigation supérieure
appBar: AppBar(
backgroundColor: Theme.of(context).colorScheme.inversePrimary,
title: Text(widget.title),
),
// Contenu principal de la page
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Text('You have pushed the button this many times:'),
Text(
'$_counter', // Affiche la variable numérique
style: Theme.of(context).textTheme.headlineMedium, // Style du texte
),
],
),
),
// Bouton flottant en bas à droite : onPressed lance _incrementCounter, tooltip est le texte d'aide, child définit l'icône
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: const Icon(Icons.add),
),
);
}
}Langage du code : JavaScript (javascript)
1. Partie point d’entrée
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
Langage du code : JavaScript (javascript)
- Importe Material, l’ensemble officiel de composants UI de Google (boutons, pages, textes, etc.). Apple dispose de son propre framework d’interface.
mainest le seul point d’entrée d’un programme Dart ;runApp()lance l’application et attache le composant racineMyApp
2. MyApp : composant racine global
C’est un StatelessWidget (composant sans état), nous détaillerons cela plus tard, retenez simplement ce point pour l’instant.
class MyApp extends StatelessWidget {
const MyApp({super.key});
// Composant racine de votre application
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
),
home: const MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
Langage du code : JavaScript (javascript)
- Paramètres globaux : nom de l’app, thème général, page d’accueil par défaut
MaterialApp: conteneur d’application au style Material, gère uniformément les routes, thèmes et titreshomedéfinit la page qui s’ouvre au lancement :MyHomePage
3. MyHomePage : page d’accueil
Page affichée par défaut à l’ouverture de la fenêtre ou de l’app, c’est un StatefulWidget (composant avec état), nous le verrons en détail ensuite.
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key, required this.title});
final String title;
@override
State<MyHomePage> createState() => _MyHomePageState();
}Langage du code : JavaScript (javascript)
- Il contient des données variables (le nombre du compteur), on utilise donc un composant avec état
- Reçoit le paramètre
titledepuis l’extérieur, accessible dans la classe d’état viawidget.title - Doit être associé à une classe
_MyHomePageStatedédiée au stockage des variables de page et de la logique d’interaction
4. _MyHomePageState
Classe de logique d’état, chargée de traiter la logique de page, l’affichage et les mises à jour de l’interface
class _MyHomePageState extends State<MyHomePage> {
int _counter = 0;
void _incrementCounter() {
setState(() {
_counter++;
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Theme.of(context).colorScheme.inversePrimary,
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Text('You have pushed the button this many times:'),
Text(
'$_counter',
style: Theme.of(context).textTheme.headlineMedium,
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: const Icon(Icons.add),
),
);
}
}Langage du code : JavaScript (javascript)
int _counter = 0: donnée variable de la page — valeur du compteur_incrementCounter(): événement au clic sur le boutonsetState()prévient Flutter que les données ont changé, il faut rafraîchir l’interface de la page- Incrémente le compteur de 1
build(): exécuté à chaque actualisation, renvoie l’intégralité de la mise en page de la page
5. Scaffold : gabarit de page
Modèle de mise en page de page, appartenant à la classe _MyHomePageState
appBar: barre de titre supérieurebody: contenu principal de la pageCentercentre les éléments,Columndispose les textes verticalement
floatingActionButton: bouton rond avec signe plus en bas à droite, lié à la méthode d’incrémentation au clic
Flux global d’exécution
- Lancement du programme → exécution de
main→ chargement deMyApp MyApprendMaterialApp→ charge la page d’accueilMyHomePage- La page affiche la barre de titre, les textes centrés et le bouton plus
- Clic sur le bouton → exécution de
_incrementCounter+setStateredessine la page → le nombre se met à jour
Comprendre notre premier projet Flutter