lifecycleScope — qu’est-ce que c’est, liaison avec Lifecycle et travail dans Android

Auteur : IT Sectr Publié le : 2026-06-23 Temps de lecture : 9 min

lifecycleScope est un CoroutineScope intégré de la bibliothèque androidx.lifecycle, lié au cycle de vie d’une Activity, d’un Fragment ou de tout LifecycleOwner, et annule automatiquement les coroutines lorsque le composant est détruit. Selon Google Android Developers, 2025, lifecycleScope permet d’exécuter en toute sécurité des coroutines liées à la couche UI sans risque d’exécuter du code après la destruction de l’Activity ou du Fragment. Le scope est automatiquement annulé lorsque le LifecycleOwner passe à l’état DESTROYED.

Points clés

  • lifecycleScope — CoroutineScope de lifecycle-runtime-ktx, annulé à l’état DESTROYED du Lifecycle
  • lifecycleScope.launch — lancement d’une coroutine qui est automatiquement annulée lorsque le LifecycleOwner est détruit
  • launchWhenStarted / launchWhenResumed — méthodes obsolètes, remplacées par repeatOnLifecycle
  • repeatOnLifecycle — API moderne pour lancer des coroutines qui suivent un état spécifique du Lifecycle
  • Dispatchers.Main.immediate — dispatcher par défaut pour lifecycleScope

Qu’est-ce que lifecycleScope dans Android ?

lifecycleScope est une propriété d’extension sur l’interface LifecycleOwner (Activity, Fragment, Service) qui fournit un CoroutineScope prêt à l’emploi, lié au cycle de vie complet du composant. Lorsque le LifecycleOwner atteint l’état DESTROYED, lifecycleScope annule automatiquement toutes les coroutines actives.

kotlin
// In Fragment or Activity
lifecycleScope.launch {
    delay(1000)
    showSnackbar("Bonjour !")
}

Contrairement à viewModelScope, lifecycleScope est annulé chaque fois que le LifecycleOwner est détruit — y compris lors de la rotation de l’écran. Cela le rend idéal pour les opérations qui ne doivent vivre que tant qu’un écran spécifique est visible.

Où lifecycleScope est disponible

lifecycleScope est disponible partout où il y a un LifecycleOwner :

  • Activity — AppCompatActivity hérite de LifecycleOwner
  • Fragment — Fragment hérite de LifecycleOwner
  • LifecycleService — un service avec cycle de vie
  • ProcessLifecycleOwner — le cycle de vie de l’application entière
  • LifecycleOwner personnalisé — tout objet implémentant LifecycleOwner

Comment fonctionne lifecycleScope : Lifecycle et annulation automatique

Le mécanisme d’annulation automatique de lifecycleScope repose sur l’abonnement aux événements Lifecycle. Lorsque le Lifecycle descend en dessous de CREATED vers DESTROYED, le scope est annulé.

États du Lifecycle

ÉtatDescriptionScope actif
CREATEDLifecycleOwner créé, onCreate exécutéOui
STARTEDLifecycleOwner visible (onStart)Oui
RESUMEDLifecycleOwner au premier plan (onResume)Oui
DESTROYEDLifecycleOwner détruit (onDestroy)Non (scope annulé)

Structure interne de lifecycleScope

lifecycleScope est créé en tant que CoroutineScope(SupervisorJob() + Dispatchers.Main.immediate) et stocké à l’intérieur du Lifecycle. Lorsque le Lifecycle passe à l’état DESTROYED, scope.cancel() est appelé. Le mécanisme est implémenté via LifecycleEventObserver, qui s’abonne aux événements du cycle de vie lors du premier accès au scope.

Comportement lors de la rotation

Lorsque l’écran est pivoté, l’Activity est détruite (onDestroy) et recréée. lifecycleScope est annulé avec l’ancienne Activity, et une nouvelle instance du scope est créée pour la nouvelle Activity. C’est une différence fondamentale avec viewModelScope, qui survit à la rotation.

API de lifecycleScope : launch, launchWhen et repeatOnLifecycle

La bibliothèque lifecycle fournit plusieurs façons de lancer des coroutines via lifecycleScope. Examinons l’évolution de l’API des méthodes obsolètes aux méthodes modernes.

lifecycleScope.launch — Lancement de base

La façon la plus simple est lifecycleScope.launch { ... }. La coroutine démarre immédiatement et est annulée à DESTROYED. Cependant, elle peut exécuter du code même lorsque l’UI n’est pas visible (par exemple, en arrière-plan après onStop). Ce n’est pas toujours souhaitable.

Obsolètes : launchWhenCreated / launchWhenStarted / launchWhenResumed

Ces méthodes mettaient en pause l’exécution de la coroutine lorsque le Lifecycle descendait en dessous de l’état spécifié et la reprenaient au retour. Cependant, elles ont été marquées @Deprecated dans lifecycle-runtime-ktx 2.6.0 parce que :

  • Elles n’annulaient pas la coroutine — seulement la mettaient en pause
  • Elles entraînaient une accumulation de coroutines suspendues consommant de la mémoire
  • Elles créaient des conditions de concurrence lors de changements rapides d’état

API moderne : repeatOnLifecycle

repeatOnLifecycle est la méthode recommandée par Google pour lancer des coroutines synchronisées avec le cycle de vie. Elle annule et redémarre la coroutine chaque fois que le Lifecycle atteint l’état spécifié.

kotlin
lifecycleScope.launch {
    repeatOnLifecycle(Lifecycle.State.STARTED) {
        viewModel.uiState.collect { state ->
            updateUI(state)
        }
    }
}

La coroutine passée à repeatOnLifecycle démarre lorsque le Lifecycle atteint STARTED et est annulée lorsqu’il descend en dessous de STARTED. Au retour à STARTED, la coroutine redémarre depuis le début. C’est sûr et efficace — aucune coroutine ne reste suspendue.

flowWithLifecycle — Pour Flow

Pour collecter des données à partir de Flow avec une connaissance du cycle de vie, il existe l’opérateur flowWithLifecycle. Il arrête et reprend automatiquement la collecte lorsque l’état du Lifecycle change :

kotlin
viewModel.uiState
    .flowWithLifecycle(lifecycle, Lifecycle.State.STARTED)
    .onEach { state -> updateUI(state) }
    .launchIn(lifecycleScope)

L’opérateur flowWithLifecycle est la façon la plus concise de s’abonner en toute sécurité à un Flow dans la couche UI.

Exemples d’utilisation de lifecycleScope

Examinons trois scénarios réels d’utilisation de lifecycleScope dans une application Android avec Kotlin.

Exemple 1 : S’abonner aux mises à jour de localisation uniquement lorsque l’écran est visible

kotlin
class MapFragment : Fragment() {

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

        lifecycleScope.launch {
            repeatOnLifecycle(Lifecycle.State.STARTED) {
                locationProvider.observeLocation().collect { loc ->
                    updateMapMarker(loc)
                }
            }
        }
    }
}

La coroutine démarre lorsque le fragment devient visible (STARTED) et est annulée lorsqu’il quitte l’écran (STOPPED). Si l’utilisateur passe à une autre application, les mises à jour de localisation ne consomment pas la batterie.

Exemple 2 : Lancer une animation au démarrage du fragment

kotlin
lifecycleScope.launch {
    repeatOnLifecycle(Lifecycle.State.RESUMED) {
        animateFadeIn(titleView)
        delay(200)
        animateSlideUp(contentView)
    }
}

L’animation s’exécute uniquement lorsque le fragment est au premier plan (RESUMED). Si l’utilisateur minimise l’application pendant l’animation, la coroutine est annulée et, au retour, l’animation redémarre.

Exemple 3 : Synchronisation périodique des données sur un écran visible

kotlin
lifecycleScope.launch {
    repeatOnLifecycle(Lifecycle.State.STARTED) {
        while (isActive) {
            syncData()
            delay(30_000L)
        }
    }
}

Les données sont synchronisées toutes les 30 secondes, mais uniquement lorsque l’écran est visible. isActive vérifie si la coroutine a été annulée, offrant une sortie sûre de la boucle lors de la sortie de l’écran.

lifecycleScope vs viewModelScope : scénarios d’utilisation

Les deux scopes sont liés au cycle de vie, mais à des aspects différents de celui-ci. Comprendre la différence est crucial pour une architecture correcte des applications Android.

Différence clé

viewModelScope est lié au ViewModel, qui survit à la rotation de l’écran. lifecycleScope est lié au LifecycleOwner (Activity/Fragment), qui est détruit et recréé lors de la rotation. Cela détermine leurs scénarios d’utilisation.

Quand utiliser lifecycleScope

  • S’abonner aux événements système (localisation, capteurs, caméra)
  • Animations et effets UI liés à un écran spécifique
  • Chargement de données par morceaux en fonction de la visibilité de l’écran
  • Opérations qui doivent s’arrêter en quittant l’écran

Quand utiliser viewModelScope

  • Chargement de données depuis un Repository
  • Logique métier qui doit survivre à la rotation
  • Mise en cache et traitement des données
  • Toute opération dont le résultat est nécessaire après la rotation

Utilisation combinée

En pratique, une combinaison des deux scopes est courante : viewModelScope charge les données et gère l’état, tandis que lifecycleScope s’abonne au Flow du ViewModel avec une connaissance du cycle de vie. Cette séparation des responsabilités est considérée comme une bonne pratique dans le développement Android moderne.

Erreurs courantes avec lifecycleScope

Examinons quatre des erreurs les plus courantes que les développeurs commettent lors de l’utilisation de lifecycleScope.

Erreur 1 : Utiliser lifecycleScope au lieu de viewModelScope pour charger des données

Si vous lancez le chargement de données dans lifecycleScope.launch, la coroutine sera annulée lors de la rotation de l’écran et les données devront être rechargées. Utilisez viewModelScope pour les opérations de longue durée. lifecycleScope est uniquement pour les tâches liées à l’UI.

Erreur 2 : Collecter Flow sans repeatOnLifecycle

Appeler directement viewModel.someFlow.collect { ... } dans lifecycleScope.launch continue de collecter des données même lorsque l’écran n’est pas visible. Cela peut entraîner des mises à jour de l’UI en arrière-plan et une surcharge inutile. Utilisez toujours repeatOnLifecycle ou flowWithLifecycle.

Erreur 3 : Oublier l’annulation en quittant l’écran

Bien que lifecycleScope soit annulé à DESTROYED, le code après un point de suspension peut ne pas s’exécuter en cas d’annulation soudaine. Ne comptez pas sur l’exécution du code après un appel suspend, sauf si vous utilisez NonCancellable.

Erreur 4 : Utiliser l’obsolète launchWhenStarted au lieu de repeatOnLifecycle

launchWhenStarted et ses équivalents n’annulent pas la coroutine, ils la mettent seulement en pause. Si l’écran bascule plusieurs fois entre le premier plan et l’arrière-plan, la coroutine accumule des appels différés. Passez à repeatOnLifecycle — c’est la seule façon correcte de se synchroniser avec le Lifecycle.

Questions fréquentes

Quelle est la différence entre lifecycleScope et GlobalScope ?

lifecycleScope est automatiquement annulé lorsque le LifecycleOwner est détruit. GlobalScope vit pendant toute la durée de l’application. Une coroutine dans lifecycleScope ne peut pas mettre à jour l’UI après la destruction du composant, contrairement à GlobalScope, ce qui entraîne des plantages. Utilisez toujours lifecycleScope dans la couche UI.

Peut-on utiliser lifecycleScope dans un ViewModel ?

Non, ViewModel n’est pas un LifecycleOwner, donc lifecycleScope n’y est pas disponible. ViewModel utilise viewModelScope. Si le code doit s’exécuter dans les deux contextes, extrayez la logique dans un use case ou un repository avec des fonctions suspend.

Que se passe-t-il lorsque repeatOnLifecycle est appelé plusieurs fois ?

Chaque appel à repeatOnLifecycle crée une nouvelle coroutine qui exécute le bloc lorsque l’état spécifié du Lifecycle est atteint. Si repeatOnLifecycle est appelé deux fois pour le même état, les deux blocs s’exécuteront indépendamment. Généralement, un seul appel dans onViewCreated suffit.

Peut-on définir un Dispatcher personnalisé pour lifecycleScope ?

Vous ne pouvez pas modifier directement le dispatcher de lifecycleScope — il utilise Dispatchers.Main.immediate. À l’intérieur du bloc de coroutine, vous pouvez passer à un autre dispatcher via withContext. Pour les tests, utilisez TestDispatcher avec LifecycleOwner.

lifecycleScope est-il annulé dans onPause ou onDestroy ?

lifecycleScope est annulé lorsque le LifecycleOwner passe à l’état DESTROYED (après onDestroy). Les simples appels lifecycleScope.launch ne sont pas annulés dans onPause ou onStop. Pour mettre en pause lors du passage en arrière-plan, utilisez repeatOnLifecycle(STARTED) ou repeatOnLifecycle(RESUMED).

Résumé

  • lifecycleScope — CoroutineScope lié à un LifecycleOwner et automatiquement annulé à DESTROYED via LifecycleEventObserver
  • Dispatchers.Main.immediate — le dispatcher par défaut, garantissant des mises à jour sûres de l’UI sans changements inutiles
  • repeatOnLifecycle — API moderne pour lancer des coroutines à un état spécifique du Lifecycle avec annulation et redémarrage automatiques
  • flowWithLifecycle — opérateur pour la collecte sûre de Flow depuis l’UI avec connaissance du cycle de vie
  • launchWhenStarted obsolète — au lieu de mettre en pause, utilisez repeatOnLifecycle qui annule la coroutine plutôt que de la mettre en pause
  • lifecycleScope vs viewModelScope — lifecycleScope pour les opérations UI (animations, localisation), viewModelScope pour les données et la logique métier
  • Rotation de l’écran — lifecycleScope est annulé lors de la rotation, viewModelScope survit ; choisissez le scope en fonction de la tâche

Nous développerons une application mobile clé en main

IT Sectr crée des applications iOS et Android pour les startups et les entreprises depuis 2017. Nous vous conseillerons et vous proposerons la meilleure solution.

Discuter du projet

Lisez aussi