Optimiser les performances Flutter : build(), keys, et const Widgets
Posté le 15 juillet 2025 • 7 min de lecture • 1 340 motsL'optimisation des performances est un enjeu crucial pour toute application mobile, et Flutter ne fait pas exception.Une application lente ou peu réactive peut nuire à l'expérience utilisateur et entraîner une désinstallation. Pour éviter cela, il est essentiel de comprendre les mécanismes internes de Flutter et d'utiliser les bonnes pratiques pour minimiser les ralentissements.

Cet article propose une amélioration des performances en se concentrant sur trois aspects fondamentaux :
Le processus build() est au cœur du rendu dans Flutter. Lorsqu’un état change ou qu’un widget est reconstruit, la méthode build() est appelée. Une mauvaise gestion de cette méthode peut causer des ralentissements notables.
Exemple : Optimisation avec des sous-composants
class OptimizedWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Column(
children: [
const Header(),
Content(),
const Footer(),
],
);
}
}Ici, seuls les widgets non-const seront reconstruits, réduisant l’impact sur les performances.
Les keys permettent de conserver l’état d’un widget lors d’une mise à jour de l’interface utilisateur. Ne pas les utiliser correctement peut entraîner des comportements inattendus.
| Type de clé | Description | Cas d’utilisation |
|---|---|---|
| GlobalKey | Permet d’accéder à un widget n’importe où | Formulaires complexes, accès direct aux états |
| ValueKey | Basée sur une valeur unique | Listes ordonnées |
| ObjectKey | Basée sur un objet | Liens dynamiques d’objets |
| UniqueKey | Génère une nouvelle clé à chaque création | Forcer la reconstruction |
Les GlobalKey permettent d’identifier un widget de manière unique dans l’ensemble de l’arborescence de widgets. Elles sont utiles pour accéder à l’état d’un widget ou pour effectuer des opérations sur ce dernier depuis n’importe quel endroit dans l’application.
Exemple :
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
void _showMessage() {
_scaffoldKey.currentState?.showSnackBar(
SnackBar(content: Text('GlobalKey en action !')),
);
}
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
key: _scaffoldKey,
appBar: AppBar(title: Text('Exemple de GlobalKey')),
body: Center(
child: ElevatedButton(
onPressed: _showMessage,
child: Text('Afficher un message'),
),
),
),
);
}
}Les ValueKey sont utilisées lorsque vous avez des éléments uniques dans une liste ou une collection. Elles sont utiles pour conserver l’état des éléments même après un réordonnancement.
**Exemple : ReorderableListView avec ValueKey**
```dart
ReorderableListView(
children: List.generate(5, (index) {
return ListTile(
key: ValueKey(index),
title: Text('Item $index'),
);
}),
onReorder: (oldIndex, newIndex) {},
)Les ObjectKey utilisent un objet comme identifiant. Cela permet de conserver l’état des widgets basés sur une instance d’objet spécifique.
Exemple :
import 'package:flutter/material.dart';
class Person {
final String name;
Person(this.name);
}
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
final List<Person> people = [
Person('Alice'),
Person('Bob'),
Person('Charlie'),
];
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: Text('Exemple de ObjectKey')),
body: ListView.builder(
itemCount: people.length,
itemBuilder: (context, index) {
return ListTile(
key: ObjectKey(people[index]),
title: Text(people[index].name),
);
},
),
),
);
}
}Les UniqueKey sont générées de manière aléatoire à chaque instanciation. Elles sont utiles lorsque vous avez besoin d’une clé toujours unique, même si les objets sont identiques.
Exemple :
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: Text('Exemple de UniqueKey')),
body: ListView(
children: List.generate(5, (index) {
return ListTile(
key: UniqueKey(),
title: Text('Item aléatoire ${index + 1}'),
);
}),
),
),
);
}
}L’utilisation du mot-clé const dans vos widgets Flutter peut considérablement améliorer les performances de votre application. Lorsqu’un widget est déclaré comme constant, il est instancié une seule fois lors de la compilation, et non à chaque rendu. Cela signifie que même si l’interface utilisateur est mise à jour, les widgets const ne sont pas reconstruits, ce qui réduit la consommation mémoire et améliore la réactivité de l’application. Les widgets marqués comme const sont également partagés en mémoire lorsqu’ils sont identiques, ce qui optimise davantage l’empreinte mémoire.
Exemple : Widget sans et avec const
// Sans const
Text('Hello', style: TextStyle(fontSize: 18));
// Avec const
const Text('Hello', style: TextStyle(fontSize: 18));| Critère | Avec const | Sans const |
|---|---|---|
| Consommation mémoire | Faible | Elevée |
| Performance de build | Optimisée | Moins performante |
| Re-rendu | Evité si immuable | Fréquent si modifié |
Les widgets qui bénéficient le plus de cette approche sont ceux qui sont naturellement immuables, c’est-à-dire dont les propriétés ne changent pas au cours de l’exécution. Parmi eux, on trouve les widgets textuels comme Text, RichText, SelectableText, mais aussi les widgets de conteneur tels que Container, Padding, et Center. Les widgets de mise en page comme Row, Column, ou encore les widgets de style comme Icon, CircleAvatar, et Divider sont également des candidats idéaux.
En adoptant systématiquement les const pour ces types de widgets, vous limitez les reconstructions inutiles, contribuant ainsi à des interfaces plus fluides et plus performantes.
Flutter DevTools est une suite d’outils de performance et de débogage pour les applications Flutter et Dart. Elle offre plusieurs fonctionnalités pour analyser et optimiser les performances de votre application :
Vue Performance : Permet de diagnostiquer les problèmes de performance et les saccades de l’interface utilisateur en affichant des informations sur le timing et les performances des activités de votre application. ( docs.flutter.dev)
Profiler CPU : Enregistre et profile une session de votre application pour analyser en détail l’activité du CPU. Cela aide à identifier les méthodes coûteuses en termes de performances. ( docs.flutter.dev)
Vue Mémoire : Affiche des informations sur l’utilisation de la mémoire de votre application et aide à identifier les fuites de mémoire potentielles. ( flutteruniversity.gitbook.io)
Utiliser des listes immuables : Préférer List.unmodifiable() pour éviter les changements non contrôlés.
Eviter les fonctions anonymes dans build() : Préférer des méthodes nommées pour réduire les calculs.
Recycler les widgets : Utiliser des ListView.builder() pour les listes volumineuses.
Tester la performance avec l’outil DevTools : Analyser les traces de build pour détecter les goulets d’étranglement.
Exemples de mesures de performance
Minimiser les reconstructions de widgets : Évitez les reconstructions inutiles en utilisant des widgets const lorsque c’est possible et en extrayant la logique des méthodes build() vers des fonctions séparées.
Utiliser des clés appropriées : L’utilisation de clés (Key) permet à Flutter de conserver l’état des widgets lors des mises à jour de l’interface utilisateur, évitant ainsi des reconstructions complètes.
Éviter les hiérarchies de widgets profondément imbriquées : Des hiérarchies complexes peuvent nuire aux performances. Simplifiez la structure de votre interface utilisateur en aplatissant les hiérarchies de widgets lorsque c’est possible.
Utiliser des widgets efficaces : Privilégiez l’utilisation de widgets tels que ListView.builder pour les longues listes, car ils construisent les éléments à la demande, améliorant ainsi les performances.
Minimiser l’utilisation de saveLayer() : Cette opération est coûteuse en performances. Utilisez-la avec parcimonie et uniquement lorsque nécessaire. (
docs.flutter.dev)
L’optimisation des performances dans Flutter repose sur une compréhension approfondie du cycle de vie des widgets, l’utilisation judicieuse des const et des keys, ainsi que l’application de bonnes pratiques de développement. En combinant ces techniques avec les outils de profilage fournis par Flutter, vous pouvez créer des applications performantes et réactives.