1. Asynchronisme : la théorie
Asynchronisme
L'asynchronisme permet d'exécuter des opérations de manière non bloquante, ce qui garantit que l'application ne fige pas lorsqu'elle attend la fin d'une tâche longue, comme une requête réseau ou l'accès à un fichier.
Dans le contexte de Flutter, l'asynchronisme est crucial pour optimiser les performances de l'application. En permettant à l'interface utilisateur de rester fluide et réactive pendant que des tâches complexes se déroulent en arrière-plan, on améliore considérablement l'expérience utilisateur. Cela évite les blocages lorsque l'application attend des données ou traite des opérations longues, comme la communication avec une API.
L'asynchronisme peut être implémenté dans un projet Flutter à l'aide de plusieurs outils, tels que les Future
et les Stream
.
Future
Un Future
représente une opération qui s'exécutera dans le futur, pouvant renvoyer une valeur ou une erreur à sa résolution. En Flutter, les Future
sont souvent utilisés pour les tâches qui ne bloquent pas l'interface utilisateur, comme les requêtes HTTP.
Pour déclarer une fonction asynchrone en Dart, on utilise le mot-clé async
, et pour attendre la résolution d'un Future
, on utilise le mot-clé await
. Cela permet de suspendre temporairement l'exécution de la fonction jusqu'à ce que le Future
soit complété.
Exemple :
Future<List<Data>> loadData() async {
final response = await http.get('https://example.com/hello');
if (response.statusCode == 200) {
return dataFromJson(response.body);
} else {
throw Exception('Failed to load data');
}
}
Exécution de plusieurs tâches asynchrones en parallèle
Pour exécuter plusieurs tâches en parallèle et attendre leur complétion, Flutter propose des méthodes comme Future.wait
. Cela est utile lorsque les tâches sont indépendantes les unes des autres. Voici comment cela fonctionne :
Future<void> performTasks() async {
await Future.wait([
task1(),
task2(),
task3(),
]);
}
Dans cet exemple, les tâches task1
, task2
, et task3
seront exécutées en parallèle et la fonction performTasks
attendra que toutes soient terminées avant de continuer.
Une autre méthode utile est Future.whenComplete
, qui permet d'exécuter une action une fois qu'un Future
est complété, qu'il ait réussi ou échoué :
Future<void> performTask() {
return task().whenComplete(() {
print('Task completed');
});
}
Stream
Un Stream
est un flux de données qui peut émettre plusieurs valeurs au fil du temps. Contrairement à un Future
qui ne renvoie qu'une seule valeur ou erreur, un Stream
peut émettre plusieurs événements successifs. Cela le rend idéal pour des cas d'utilisation comme les notifications push, les mises à jour en temps réel, ou le suivi de données dynamiques.
En Flutter, les Stream
sont souvent combinés avec le widget StreamBuilder
, qui permet de construire dynamiquement l'interface utilisateur en fonction des données reçues via un Stream
.
Exemple d'implémentation d'un Stream
qui émet la position de l'utilisateur toutes les secondes :
Stream<UserPosition> getUserLocationStream() {
return Stream.periodic(Duration(seconds: 1), (count) {
return UserPosition(45.521563, -122.677433);
});
}
Pour afficher cette position sur une carte et mettre à jour l'interface utilisateur en temps réel, vous pouvez utiliser un StreamBuilder
:
StreamBuilder<UserPosition>(
stream: getUserLocationStream(),
builder: (context, snapshot) {
if (snapshot.hasData) {
return Text('Position: ${snapshot.data!.latitude}, ${snapshot.data!.longitude}');
} else {
return CircularProgressIndicator();
}
},
)
Ce widget réagira automatiquement aux nouveaux événements du Stream
et mettra à jour l'interface en conséquence.
Conclusion
L'asynchronisme est un concept fondamental pour améliorer les performances et la réactivité des applications Flutter. Les Future
et Stream
sont des outils puissants qui permettent de gérer des opérations longues ou répétitives de manière efficace, sans bloquer l'interface utilisateur.