Le quartierK KotlinPièce 6/7Avancé

Coroutines et Jetpack Compose

Lancer des tâches en parallèle avec les coroutines (suspend, launch, async), puis découvrir Jetpack Compose avec des fonctions @Composable.

Ce que tu vas apprendre

  • Écrire une fonction suspend et lancer des coroutines avec launch et async.
  • Comprendre à quoi servent les coroutines dans une application.
  • Lire une fonction @Composable simple de Jetpack Compose.

Pourquoi des coroutines

Charger une recette depuis Internet prend du temps. Si le programme attend sans rien faire, l'écran se fige.

Une coroutine est une tâche qui peut se mettre en pause sans bloquer le reste du programme. Elle reprend quand le résultat est prêt. Les coroutines ne sont pas dans le langage seul : elles viennent de la bibliothèque kotlinx.coroutines.

implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.11.0")

Cette ligne s'ajoute dans le fichier de build Gradle de ton projet.

suspend : une fonction qui peut attendre

import kotlinx.coroutines.*
import kotlin.time.Duration.Companion.seconds

suspend fun chargerRecette(): String {
    delay(1.seconds)
    return "Tarte aux pommes"
}

Le mot-clé suspend marque une fonction qui peut être mise en pause. delay attend sans bloquer le fil d'exécution.

Une fonction suspend ne peut être appelée que depuis une autre fonction suspend ou depuis une coroutine.

coroutineScope et launch

suspend fun main() {
    coroutineScope {
        launch { println("Pâte prête") }
        launch { println("Garniture prête") }
    }
    println("Tout est prêt")
}

coroutineScope ouvre un espace où vivent des coroutines, et attend qu'elles aient toutes fini avant de continuer.

launch démarre une nouvelle coroutine sans bloquer le reste. Elle renvoie un Job, un identifiant de la tâche en cours.

async et await

suspend fun main() = coroutineScope {
    val titre = async { chargerTitre() }
    val photo = async { chargerPhoto() }
    println("${titre.await()} - ${photo.await()}")
}

async lance un calcul concurrent et renvoie un Deferred, une promesse de résultat. await() met en pause jusqu'à ce que la valeur soit prête.

Les deux chargements démarrent ensemble : le temps total est celui du plus long.

OutilRôleRenvoie
launchLancer une tâche sans résultatJob
asyncLancer un calcul avec résultatDeferred
coroutineScopeRegrouper et attendre des coroutinesLe résultat de son bloc
runBlocking bloque le fil courant jusqu'à la fin de son contenu. N'en fais pas ton réflexe.

Jetpack Compose en un coup d'oeil

Jetpack Compose est la boîte à outils moderne d'Android pour construire une interface avec des fonctions Kotlin. Au lieu de décrire l'écran dans un fichier séparé, tu l'écris en code.

import androidx.compose.material3.Text
import androidx.compose.runtime.Composable

@Composable
fun CarteRecette(titre: String) {
    Text(text = "Recette : $titre")
}

Une fonction marquée @Composable décrit une partie de l'écran. Text est un composable fourni par la bibliothèque. Un composable ne peut être appelé que depuis un autre composable.

Afficher la fonction à l'écran

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            CarteRecette("Tarte aux pommes")
        }
    }
}

setContent définit le contenu d'une activité, c'est-à-dire d'un écran de l'application. C'est le point d'entrée de tes composables.

Un état avec remember

@Composable
fun Compteur() {
    var portions by remember { mutableStateOf(4) }
    Button(onClick = { portions += 1 }) {
        Text("Portions : $portions")
    }
}

Un état est une valeur qui change au cours du temps. mutableStateOf crée une valeur observable par Compose. Quand elle change, les composables qui la lisent sont redessinés.

remember conserve la valeur entre deux redessins. Sans lui, portions repartirait de 4 à chaque fois.

Une liste de recettes

@Composable
fun ListeRecettes(titres: List<String>) {
    LazyColumn {
        items(titres) { titre ->
            CarteRecette(titre)
        }
    }
}

LazyColumn affiche une liste verticale qui ne construit que les éléments visibles. Le bloc passé à items est une lambda, comme celles du cours précédent.

À retenir

  • Une coroutine est une tâche qui peut se mettre en pause sans bloquer le programme.
  • Une fonction suspend ne s'appelle que depuis une autre fonction suspend ou une coroutine.
  • launch lance sans résultat, async renvoie un Deferred dont on lit la valeur avec await().
  • coroutineScope attend la fin des coroutines qu'il contient ; évite runBlocking.
  • Une fonction @Composable décrit un morceau d'interface et s'affiche via setContent.
  • remember et mutableStateOf gardent un état et redessinent l'écran quand il change.

Pour aller plus loin

Sources officielles

Ensuite

Projet
Lignes de code
Niveau
Le quartier
Appartement
Kotlin
Pièce
6/7
Plan n°
kotlin/06.coroutines-et-compose
Lignes de code · fiches rédigées à partir des documentations officielles, sources citées en bas de chaque page.