Guide complet des coroutines Kotlin : maĆ®triser launch, async et await

  • DiffĆ©rences fondamentales entre l'utilisation de launch pour les tĆ¢ches sans retour et async pour obtenir des rĆ©sultats en utilisant await.
  • Gestion efficace des threads Ć  l'aide de Dispatchers.Main, IO et Default pour Ć©viter le blocage de l'interface utilisateur.
  • Mise en œuvre d'une concurrence structurĆ©e et d'un contrĆ“le du cycle de vie Ć  l'aide de CoroutineScope et Job.

Coroutines Kotlin : maĆ®triser launch, async et await

Si votre application Android s'est déjà figée ou n'a plus répondu pendant un téléchargement, vous rencontrez probablement des problèmes avec le thread principal. Dans le monde du développement mobile, assurer une fluidité optimale lors de l'exécution de tâches exigeantes est un véritable défi, et c'est là que les coroutines Kotlin entrent en jeu . Elles nous permettent d'écrire du code asynchrone sans nous enliser dans des rappels interminables.

Imaginez les coroutines comme des threads lĆ©gers ; elles ne crĆ©ent pas un nouveau thread systĆØme Ć  chaque exĆ©cution, mais exploitent des groupes de threads existants et un systĆØme d'ordonnancement trĆØs ingĆ©nieux. Cela les rend incroyablement efficaces, et le code se lit de maniĆØre quasi sĆ©quentielle, mĆŖme si une multitude de pauses et de reprises se dĆ©roulent en arriĆØre-plan , de sorte que l'utilisateur ne perƧoit aucun dĆ©calage Ć  l'Ć©cran.

Le secret de la suspension : suspendre et reprendre

Contrairement aux fonctions classiques, les coroutines introduisent deux concepts clĆ©s. PremiĆØrement, `suspend` permet de suspendre l'exĆ©cution d'une tĆ¢che tout en sauvegardant son Ć©tat. DeuxiĆØmement, `resume` reprend l'exĆ©cution exactement lĆ  où elle s'Ć©tait arrĆŖtĆ©e. Il est important de noter qu'une fonction suspendue ne bloque pas le thread sur lequel elle s'exĆ©cute ; elle se met simplement en pause pour permettre Ć  d'autres tĆ¢ches de se poursuivre pendant qu'elle attend une rĆ©ponse, par exemple d'une base de donnĆ©es.

Il est essentiel de comprendre que l'utilisation du mot-clƩ `suspend` ne dƩplace pas automatiquement le code vers un thread secondaire. Pour garantir la sƩcuritƩ du programme principal , il est nƩcessaire d'associer ces fonctions Ơ des dispatchers appropriƩs, afin d'Ʃviter que les opƩrations gourmandes en ressources ne saturent l'interface utilisateur.

Coroutines Kotlin : maĆ®triser launch, async et await
Article connexe:
Guide complet de Kotlin pour les dĆ©veloppeurs Android : concepts et fondamentaux

RĆ©partiteurs : Où la magie opĆØre-t-elle ?

Pour indiquer Ć  Kotlin quel thread utiliser pour exĆ©cuter chaque portion de code, on utilise des Dispatchers . Tous les Dispatchers n'ont pas la mĆŖme fonction ; il est donc important de savoir choisir le bon.

  • RĆ©partiteurs.PrincipalCet outil permet d'interagir avec l'interface utilisateur. Il ne doit ĆŖtre utilisĆ© que pour des modifications visuelles rapides ou pour interagir avec LiveData, car toute opĆ©ration complexe entraĆ®nera une erreur. Application ne rĆ©pondant pas (ANR).
  • Dispatchers.IOIl est optimisĆ© pour les tĆ¢ches d'entrĆ©e/sortie. C'est le site idĆ©al pour appels API, lire des fichiers sur le disque ou gĆ©rer la base de donnĆ©es Room.
  • Dispatchers.DefaultConƧu pour les tĆ¢ches gourmandes en ressources processeur, par exemple lorsque vous avez besoin de traiter un JSON gĆ©ant ou trier une trĆØs longue liste d'Ć©lĆ©ments.

Une technique courante et recommandée consiste à utiliser `withContext` . Cette fonction permet de modifier le dispatcher au sein d'une fonction suspendue sans avoir recours à des callbacks. Ainsi, le développeur appelant la fonction n'a pas à se soucier du thread d'exécution, car la fonction elle-même assure sa propre sécurité en basculant en interne vers le thread d'E/S ou le thread par défaut.

Lancement ou asynchrone : lequel choisir ?

Lorsque nous voulons démarrer une coroutine, nous avons deux voies principales selon que la tâche doit renvoyer une valeur ou non.

L' opĆ©rateur `launch` est ce que l'on appelle une exĆ©cution Ā« sans retour Ā». Il est utilisĆ© pour les tĆ¢ches qui ne renvoient pas de rĆ©sultat, comme la mise Ć  jour d'une couleur Ć  l'Ć©cran ou l'enregistrement de donnĆ©es dans le cache. Il renvoie un objet `Job` , qui est en quelque sorte une tĆ©lĆ©commande permettant d'annuler la coroutine si nĆ©cessaire.

En revanche, `async` est utilisĆ© lorsqu'une valeur de retour est nĆ©cessaire. Cet opĆ©rateur renvoie un `Deferred<T>` , qui est une sorte de promesse d'un rĆ©sultat ultĆ©rieur. Pour obtenir cette valeur, il faut appeler la fonction `await()` , qui suspend l'exĆ©cution jusqu'Ć  ce que le rĆ©sultat soit disponible. L'un des atouts de `async` est qu'il permet les appels parallĆØles ; si trois requĆŖtes `async` sont effectuĆ©es, elles seront toutes trois envoyĆ©es au serveur simultanĆ©ment, optimisant ainsi le temps d'attente total.

Gestion structurƩe de la concurrence et du cycle de vie

Pour éviter que les coroutines ne continuent de s'exécuter après la fermeture de l'écran par l'utilisateur (ce qui provoquerait des fuites de mémoire), Kotlin utilise la concurrence structurée . Celle-ci est gérée par le biais de CoroutineScope , qui recense toutes les coroutines lancées en son sein.

Sous Android, il est courant d'utiliser des portées prédéfinies comme `viewModelScope` ou `lifecycleScope` . Celles-ci sont très pratiques car elles annulent automatiquement toutes les tâches en cours lorsque le `ViewModel` est détruit ou que l'`Activity` se termine. Si vous devez créer votre propre portée, vous pouvez combiner un `Job` et un `Dispatcher`, mais n'oubliez jamais d'appeler ` scope.cancel()` dans la méthode de nettoyage de votre classe.

Gestion des erreurs et des cas particuliers

La gestion des exceptions varie selon le constructeur utilisƩ. Avec `launch` , si une erreur survient et n'est pas interceptƩe, l'application se ferme immƩdiatement. En revanche, avec `async` , l'exception est stockƩe dans l'objet `Deferred` et ne sera levƩe que lors de l'appel Ơ ` await()` , ce qui peut parfois entraƮner des erreurs non dƩtectƩes si l'on n'y prend pas garde.

Pour gérer cela naturellement, il est préférable d'encapsuler les appels dans des blocs try-catch , ce qui rend le code asynchrone aussi simple à écrire que le code synchrone. De plus, si l'on souhaite qu'une coroutine soit insensible à l'annulation par son parent, on peut utiliser `NonCancellable` avec `withContext`, mais il faut procéder avec une extrême prudence afin de ne pas rompre la hiérarchie de concurrence.

L'intégration de tout cela avec des bibliothèques comme Retrofit est un jeu d'enfant, car les versions modernes prennent en charge nativement les fonctions suspendues. En définitive, le flux de travail idéal consiste à ce que le ViewModel lance la coroutine, le Repository gère la logique métier et la source de données effectue la requête auprès de Dispatchers.IO , tout en conservant une interface fluide et un code propre.

Comment migrer proprement la couche d'une application Android d'entreprise vers Kotlin Multiplatform
Article connexe:
Comment migrer proprement la couche d'une application Android d'entreprise vers Kotlin Multiplatform

L'utilisation des coroutines révolutionne le développement Android, remplaçant la complexité des threads traditionnels par un système de suspension efficace et des portées limitées dans le cycle de vie. En comprenant la différence entre l'exécution rapide de `launch` et la puissance du traitement parallèle de `async` avec `await`, et en choisissant judicieusement les dispatchers, vous pouvez créer des logiciels robustes qui optimisent les ressources de l'appareil sans nuire à l'expérience utilisateur. Partagez ce guide pour en faire profiter d'autres utilisateurs.


Google Play Store sans compte Google
Il peut vous intƩresser:
Comment tƩlƩcharger des applications depuis le Play Store sans avoir de compte Google
Ajouter comme source prƩfƩrƩe dans Google