Programmation réactive en Kotlin : la bibliothèque kotlinx.coroutines et Flow

Formateur Python en ligne pour débutants

Apprenez Python facilement sans surcharge théorique. Résolvez des tâches pratiques avec vérification automatique et écrivez du code directement dans le navigateur.

Start Course

Programmation réactive en Kotlin : la puissance de kotlinx.coroutines et Flow

\n\n

La programmation réactive est un paradigme orienté vers le traitement asynchrone des flux de données et la propagation des changements. Dans l'écosystème Kotlin, l'outil principal pour implémenter des modèles réactifs est la bibliothèque kotlinx.coroutines, et plus précisément son composant Flow. Contrairement à RxJava, Flow est étroitement intégré aux coroutines, rendant le code plus concis et plus sûr.

\n\n

Concepts fondamentaux de Flow

\n\n

Flow est un flux de données asynchrone froid qui émet des valeurs séquentiellement. Il prend en charge :

\n
    \n
  • Les flux froids — les données ne commencent à être générées qu'en présence d'un abonné (opérateur terminal).
  • \n
  • Le contexte d'exécution — le flux peut basculer entre différents répartiteurs de coroutines.
  • \n
  • L'annulation via les coroutines — l'annulation de la coroutine parente termine automatiquement le Flow.
  • \n
\n\n

Installation et configuration

\n

Pour utiliser Flow, ajoutez la dépendance dans build.gradle.kts :

\n
dependencies {\n    implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.8.1")\n}
\n\n

Création et consommation d'un Flow

\n

Créons un flux simple de nombres avec un délai :

\n
import kotlinx.coroutines.*\nimport kotlinx.coroutines.flow.*\n\nfun simpleFlow(): Flow<Int> = flow {\n    for (i in 1..5) {\n        delay(100) // simulation d'un travail asynchrone\n        emit(i)    // émet la valeur\n    }\n}\n\nfun main() = runBlocking {\n    simpleFlow().collect { value ->\n        println("Reçu : $value")\n    }\n}
\n

Dans cet exemple, flow { ... } crée un flux froid, et collect est l'opérateur terminal qui déclenche l'exécution.

\n\n

Transformation des données avec des opérateurs

\n

Flow fournit un riche ensemble d'opérateurs, similaires à RxJava :

\n
    \n
  • map — transforme chaque valeur.
  • \n
  • filter — filtre les valeurs selon une condition.
  • \n
  • flatMapConcat — concatène séquentiellement les flux.
  • \n
  • catch — gère les exceptions à l'intérieur du flux.
  • \n
\n

Exemple avec des opérateurs :

\n
fun transformFlow(): Flow<String> = flow {\n    emit("Kotlin")\n    emit("Java")\n    emit("Python")\n}.map { it.lowercase() }\n .filter { it.startsWith("k") }\n\nfun main() = runBlocking {\n    transformFlow().collect { println(it) }\n    // Sortie : kotlin\n}
\n\n

Gestion des erreurs et de la fin

\n

Flow permet de gérer élégamment les exceptions avec catch et d'exécuter des actions de fin via onCompletion :

\n
fun errorProneFlow(): Flow<Int> = flow {\n    emit(1)\n    emit(2)\n    throw RuntimeException("Erreur !")\n    emit(3) // ne sera pas exécuté\n}\n\nfun main() = runBlocking {\n    errorProneFlow()\n        .catch { e -> println("Erreur attrapée : ${e.message}") }\n        .onCompletion { println("Flux terminé") }\n        .collect { println(it) }\n}\n// Sortie : 1, 2, Erreur attrapée : Erreur !, Flux terminé
\n\n

Flux chauds : StateFlow et SharedFlow

\n

Contrairement au Flow froid, StateFlow et SharedFlow sont des flux chauds qui conservent un état et peuvent avoir plusieurs abonnés.

\n\n

StateFlow

\n

Utilisé pour stocker et observer un état (par exemple, dans un ViewModel) :

\n
class CounterViewModel {\n    private val _counter = MutableStateFlow(0)\n    val counter: StateFlow<Int> = _counter.asStateFlow()\n\n    fun increment() {\n        _counter.value++\n    }\n}\n\n// Dans une Activity ou un Fragment\nlifecycleScope.launch {\n    viewModel.counter.collect { value ->\n        textView.text = "Compteur : $value"\n    }\n}
\n\n

SharedFlow

\n

Adapté pour

Recommendations