Flutter Widgets — ce que c'est, arbre de widgets et build

Auteur : IT Sectr Publié le : 2026-02-21 Temps de lecture : 8 min

Flutter Widgets — les blocs de construction fondamentaux de l'interface utilisateur dans le framework Google Flutter, publié en version stable 1.0 en décembre 2018. Dans Flutter, tout est un widget : des écrans et boutons aux espacements et alignements. Les widgets forment un arbre (widget tree) que Flutter rend sur son propre moteur Skia/Impeller, en contournant les composants natifs de la plateforme. Selon Google I/O (2025), Flutter est utilisé dans plus de 500 000 applications sur Google Play et l'App Store. L'architecture Flutter divise les widgets en StatelessWidget (immuables) et StatefulWidget (avec état mutable via un objet State).

Points Clés

  • Flutter Widgets — tous les éléments d'UI dans Flutter : des écrans et boutons aux espacements et alignements ; le framework n'utilise pas les composants natifs de la plateforme.
  • StatelessWidget — un widget sans état mutable ; affiche les données passées via le constructeur et ne change pas après le build.
  • StatefulWidget — un widget avec état mutable stocké dans un objet State séparé qui survit aux rebuilds.
  • Arbre de widgets (widget tree) — une hiérarchie de widgets décrivant l'UI ; Flutter la transforme en Element Tree et Render Tree pour le rendu.
  • BuildContext — le contexte de construction fournissant l'accès à la position du widget dans l'arbre, au thème, à MediaQuery et à InheritedWidget.

Que sont les Flutter Widgets ?

Flutter Widgets — tous les éléments d'UI dans le framework Flutter, implémentés en tant que classes Dart immuables. Un widget est la configuration d'un élément d'UI : sa taille, sa couleur, sa position et ses gestionnaires d'événements. Contrairement à Android (XML + View) ou iOS (Storyboard + UIView), Flutter n'utilise pas de composants natifs — tout est dessiné par le moteur Skia (Android/iOS/Linux) ou Impeller (iOS/macOS) sur un Canvas. Cela garantit une apparence cohérente sur toutes les plateformes sans divergence de plateforme. Flutter est livré avec deux ensembles de widgets : Material Widgets (Google Material Design 3 pour Android/web) et Cupertino Widgets (Apple HIG pour iOS/macOS). Le développeur peut combiner les deux ensembles dans une seule application. Chaque widget a une méthode build() qui retourne un widget enfant ou une composition de ceux-ci — c'est ainsi que l'arbre de widgets est construit.

Les trois arbres de Flutter

Flutter fonctionne avec trois arbres : Widget Tree (configuration, créée par le développeur), Element Tree (mapping du widget à sa position dans l'arbre, géré par le framework) et Render Tree (objets qui calculent la disposition et effectuent le peinture). Un Widget crée un Element, qui crée un RenderObject. L'Element est réutilisé lors d'un changement de configuration (rebuild) — c'est le mécanisme d'optimisation de Flutter : si le type de widget et la key correspondent, l'Element n'est pas recréé mais mis à jour avec la nouvelle configuration. Comprendre les trois arbres est la clé pour optimiser les performances des applications Flutter.

StatelessWidget : widgets immuables

StatelessWidget — un widget qui ne stocke pas d'état interne. Il reçoit des paramètres via le constructeur et les affiche sans possibilité de modification après le build. StatelessWidget est idéal pour les éléments statiques : en-têtes, icônes, avatars, listes avec données fixes. La méthode build() est appelée une fois à la création et lorsque le widget parent change. Comme StatelessWidget n'a pas d'état, il ne nécessite pas d'objet State séparé — build() est défini directement dans la classe du widget.

dart
import 'package:flutter/material.dart';

class ProfileHeader extends StatelessWidget {
  final String name;
  final String avatarUrl;

  const ProfileHeader({super.key, required this.name, required this.avatarUrl});

  @override
  Widget build(BuildContext context) {
    return Row(
      children: [
        CircleAvatar(
          radius: 24,
          backgroundImage: NetworkImage(avatarUrl),
        ),
        const SizedBox(width: 12),
        Text(
          name,
          style: const TextStyle(
            fontSize: 18,
            fontWeight: FontWeight.bold,
          ),
        ),
      ],
    );
  }
}

ProfileHeader — un StatelessWidget qui reçoit name et avatarUrl via le constructeur. CircleAvatar affiche l'avatar, Text affiche le nom. Le widget ne peut pas modifier ces valeurs après la création. Utiliser un constructeur const (const ProfileHeader) permet à Flutter de réutiliser l'instance du widget lors du rebuild du parent — une micro-optimisation recommandée pour tous les StatelessWidget.

StatefulWidget : widgets avec état

StatefulWidget — un widget avec état mutable stocké dans un objet State séparé. Le StatefulWidget lui-même est immuable, comme StatelessWidget. La partie mutable est déléguée à State : State est un objet créé une fois qui survit à de multiples rebuilds du widget. Lorsque l'état change (setState()), Flutter appelle build() sur State, mettant à jour l'UI. StatefulWidget est utilisé pour les éléments interactifs : compteurs, champs de texte, cases à cocher, animations, minuteries.

dart
import 'package:flutter/material.dart';

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

  @override
  State<LikeButton> createState() => _LikeButtonState();
}

class _LikeButtonState extends State<LikeButton> {
  bool liked = false;
  int count = 42;

  void _toggleLike() {
    setState(() {
      liked = !liked;
      count += liked ? 1 : -1;
    });
  }

  @override
  Widget build(BuildContext context) {
    return ElevatedButton(
      onPressed: _toggleLike,
      child: Text(liked ? '♥ $count' : '♡ $count'),
    );
  }
}

LikeButton — un StatefulWidget avec la classe State _LikeButtonState. Les champs liked et count sont l'état stocké dans State et ne sont pas réinitialisés lors du rebuild. setState() notifie Flutter que l'UI doit être reconstruite. Flutter ne recrée pas State à chaque rebuild du parent — seulement lorsque la configuration change (key ou type de widget). Chez IT Sectr, nous utilisons StatelessWidget pour l'affichage et StatefulWidget pour les composants interactifs, suivant le principe de minimiser StatefulWidget jusqu'aux limites de la mutation.

Arbre de widgets : de Widget à RenderObject

Widget Tree — une structure hiérarchique de widgets décrivant l'UI de l'application. Flutter convertit le Widget Tree en Element Tree : chaque Widget crée un Element, qui suit sa position dans l'arbre et sa connexion à un RenderObject. Le Render Tree effectue la disposition (détermination des tailles et positions) et le peinture (rendu). L'Element est une couche d'optimisation clé : si le type de widget et la key n'ont pas changé lors d'un rebuild, l'Element est réutilisé, mettant à jour la configuration sans recréer le RenderObject. Cela garantit les performances de Flutter à des taux d'images élevés (60/120 FPS).

dart
import 'package:flutter/material.dart';

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Widgets Flutter')),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            const Icon(Icons.flutter_dash, size: 80),
            const SizedBox(height: 16),
            const Text(
              'Bonjour, Flutter !',
              style: TextStyle(fontSize: 24),
            ),
          ],
        ),
      ),
    );
  }
}

Arbre de widgets HomeScreen : Scaffold → AppBar + Center → Column → [Icon, SizedBox, Text]. Scaffold est le widget racine de disposition Material Design. Center centre sa Column fille. Column dispose les enfants verticalement avec un alignement centré (mainAxisAlignment.center). Flutter calcule la disposition de haut en bas (les contraintes sont passées du parent) et les tailles de bas en haut (sizedByParent ou dimensionnement à partir des enfants).

BuildContext : contexte de construction et accès à l'arbre

BuildContext — un descripteur de la position du widget dans l'Element Tree. Chaque méthode build() reçoit un BuildContext, à travers lequel le widget peut accéder à : MediaQuery (taille de l'écran, orientation, densité de pixels, zone de sécurité), Theme (MaterialThemeData ou CupertinoThemeData), Navigator (pile de navigation), ScaffoldMessenger (SnackBar), InheritedWidget (passage de données vers le bas dans l'arbre). BuildContext ne doit pas être sauvegardé après la fin de build() ou utilisé en dehors d'un contexte synchrone — cela provoque des erreurs comme « Scaffold.of() called with a context that does not contain a Scaffold ». Au lieu de sauvegarder le context, utilisez le widget Builder ou le modèle InheritedWidget pour accéder aux données.

Key : identification du widget dans l'arbre

Key — un paramètre optionnel du constructeur de chaque widget (super.key). Key aide Flutter à identifier un widget lorsque l'ordre ou le nombre d'éléments dans une liste change. Sans key, Flutter compare les widgets par type et position ; lors de l'ajout d'un élément au milieu d'une liste sans key, Flutter réutilise l'Element pour le mauvais widget, provoquant des bogues d'état (StatefulWidget) et des problèmes d'animation. Utilisez ValueKey (identifiant unique) pour les listes, ObjectKey (basé sur l'objet de données), UniqueKey (garanti unique à chaque rebuild — pour une recréation forcée).

Catalogue de widgets Flutter : Material, Cupertino, Layout

Flutter SDK (version stable 3.3+, Dart 3+) inclut plus de 200 widgets intégrés divisés en catégories : Layout (Row, Column, Stack, Container, Expanded, Flexible, Wrap, GridView, ListView, CustomScrollView), Material Design (Scaffold, AppBar, Card, Drawer, BottomNavigationBar, FloatingActionButton, TabBar, Chip, DataTable), Cupertino (CupertinoPageScaffold, CupertinoNavigationBar, CupertinoButton, CupertinoTabBar), Painting & Effects (Opacity, DecoratedBox, ClipRect, Transform, BackdropFilter, ShaderMask), Async (FutureBuilder, StreamBuilder) et Accessibility (Semantics, MergeSemantics, ExcludeSemantics). Les widgets de disposition sont la base de toute UI Flutter : Row pour les séquences horizontales, Column pour les verticales, Stack pour les éléments superposés, Container avec BoxDecoration pour la décoration.

CatégorieWidgets clésObjectif
LayoutRow, Column, Stack, Container, Expanded, FlexiblePositionnement et dimensionnement des enfants
MaterialScaffold, AppBar, Card, Drawer, FAB, TabBarComposants UI Material Design 3
CupertinoCupertinoPageScaffold, CupertinoNavigationBar, CupertinoButtonComposants stylisés iOS
PaintingOpacity, ClipRect, Transform, DecoratedBox, BackdropFilterEffets visuels et clipping
AsyncFutureBuilder, StreamBuilderChargement de données asynchrone avec états d'UI
AccessibilitySemantics, MergeSemanticsBalisage sémantique pour lecteurs d'écran

Questions Fréquentes

En quoi StatelessWidget diffère-t-il de StatefulWidget ?

StatelessWidget n'a pas d'état interne — toutes les données sont passées via le constructeur et ne changent pas. StatefulWidget stocke l'état mutable dans un objet State séparé qui survit aux rebuilds. Le changement d'état appelle setState(), et Flutter reconstruit l'UI. Utilisez StatelessWidget pour les éléments immuables ; utilisez StatefulWidget pour les éléments interactifs.

Qu'est-ce que BuildContext dans Flutter ?

BuildContext est un descripteur de la position du widget dans l'Element Tree, passé à la méthode build(). Via le context, un widget accède à MediaQuery, Theme, Navigator, ScaffoldMessenger et InheritedWidget. BuildContext ne doit pas être sauvegardé après la fin de build(). Pour accéder aux données, utilisez le widget Builder ou InheritedWidget.

Faut-il connaître Dart pour travailler avec Flutter ?

Oui, Flutter utilise Dart comme son unique langage de programmation. Dart est un langage typé statiquement avec null safety, sound null safety, extension methods et pattern matching. Pour commencer, les bases de Dart suffisent : classes, fonctions, async/await, collections. Dart se compile en code natif (AOT) via Dart Native et en JavaScript (pour le web) via Dart2JS.

Flutter est-il uniquement pour les plateformes mobiles ?

Non, Flutter prend en charge six plateformes : iOS, Android, Web, macOS, Windows, Linux. Plus de 90 % du code est partagé entre toutes les plateformes. Les adaptations de plateforme (appareil photo, système de fichiers) sont implémentées via des plugins ou des platform channels. Pour le bureau, Flutter utilise le shell de fenêtrage Flutter Desktop ; pour le web, il utilise le moteur CanvasKit (WebGL) ou le moteur de rendu HTML.

Comment Flutter atteint-il des performances de 60 FPS ?

Flutter atteint 60/120 FPS grâce à : son propre moteur 2D (Skia/Impeller), l'absence de pont natif (contrairement à React Native), trois arbres (Widget → Element → Render) avec réutilisation d'Element lorsque le type/la key reste inchangé, un algorithme de disposition à passage unidirectionnel (contraintes vers le bas, tailles vers le haut) et RepaintBoundary pour isoler le repeint de zones individuelles de l'écran.

Résumé

  • Flutter Widgets — tous les éléments d'UI : de Scaffold à SizedBox ; Flutter les rend lui-même sur Skia/Impeller, sans utiliser de composants natifs.
  • StatelessWidget — un widget sans état ; build() retourne l'UI basée sur des paramètres de constructeur immuables.
  • StatefulWidget — un widget avec état mutable dans State ; setState() déclenche le rebuild de l'UI.
  • Trois arbres Flutter : Widget (configuration) → Element (position) → Render (disposition + peinture) ; Element est réutilisé pour les performances.
  • BuildContext — la position du widget dans l'arbre ; accès à MediaQuery, Theme, Navigator, InheritedWidget.
  • Material et Cupertino — deux ensembles de widgets pour Google Material Design 3 et Apple HIG respectivement.
  • Key (ValueKey, ObjectKey, UniqueKey) — identification du widget lors du changement d'ordre ou de quantité dans une liste.

Nous développerons une application mobile clé en main

IT Sectr crée des applications iOS et Android pour les startups et les entreprises depuis 2017. Nous vous conseillerons et vous proposerons la meilleure solution.

Discuter du projet

Lisez aussi