lifecycleScope — is een ingebouwde CoroutineScope uit de androidx.lifecycle-bibliotheek, die is gekoppeld aan de levenscyclus van Activity, Fragment of elke LifecycleOwner en automatisch coroutines annuleert bij vernietiging van de component. Volgens Google Android Developers, 2025 maakt lifecycleScope het mogelijk om veilig coroutines te starten die aan de UI-laag zijn gekoppeld, zonder het risico code uit te voeren na vernietiging van Activity of Fragment. De scope wordt automatisch geannuleerd wanneer LifecycleOwner de status DESTROYED bereikt.
Belangrijkste punten
lifecycleScope — is een extensie-eigenschap op de LifecycleOwner-interface (Activity, Fragment, Service) die een kant-en-klare CoroutineScope biedt die is gekoppeld aan de volledige levenscyclus van de component. Wanneer LifecycleOwner de status DESTROYED bereikt, annuleert lifecycleScope automatisch alle actieve coroutines.
// In Fragment of Activity
lifecycleScope.launch {
delay(1000)
showSnackbar("Hallo!")
}
In tegenstelling tot viewModelScope wordt lifecycleScope geannuleerd bij elke vernietiging van LifecycleOwner — inclusief schermrotatie. Dit maakt het ideaal voor bewerkingen die alleen moeten leven zolang een specifiek scherm zichtbaar is.
lifecycleScope is overal beschikbaar waar een LifecycleOwner is:
Het mechanisme voor automatische annulering van lifecycleScope is gebaseerd op abonnement op Lifecycle-gebeurtenissen. Wanneer Lifecycle onder CREATED naar DESTROYED zakt, wordt de scope geannuleerd.
| Status | Beschrijving | Scope actief |
|---|---|---|
| CREATED | LifecycleOwner aangemaakt, onCreate uitgevoerd | Ja |
| STARTED | LifecycleOwner zichtbaar (onStart) | Ja |
| RESUMED | LifecycleOwner op de voorgrond (onResume) | Ja |
| DESTROYED | LifecycleOwner vernietigd (onDestroy) | Nee (scope geannuleerd) |
lifecycleScope wordt aangemaakt als CoroutineScope(SupervisorJob() + Dispatchers.Main.immediate) en opgeslagen in Lifecycle. Bij overgang van Lifecycle naar de status DESTROYED wordt scope.cancel() aangeroepen. Het mechanisme is geïmplementeerd via LifecycleEventObserver, die zich bij eerste toegang tot de scope abonneert op levenscyclusgebeurtenissen.
Bij schermrotatie wordt Activity vernietigd (onDestroy) en opnieuw aangemaakt. lifecycleScope wordt samen met de oude Activity geannuleerd en een nieuw exemplaar van de scope wordt aangemaakt voor de nieuwe Activity. Dit is een fundamenteel verschil met viewModelScope, die behouden blijft bij rotatie.
De lifecycle-bibliotheek biedt verschillende manieren om coroutines te starten via lifecycleScope. Laten we de evolutie van de API van verouderde naar moderne methoden bekijken.
De eenvoudigste manier — lifecycleScope.launch { ... }. De coroutine start onmiddellijk en wordt geannuleerd bij DESTROYED. Het kan echter code uitvoeren zelfs wanneer UI niet zichtbaar is (bijvoorbeeld op de achtergrond na onStop). Dit is niet altijd wenselijk.
Deze methoden onderbraken de uitvoering van de coroutine wanneer Lifecycle onder de opgegeven status zakte en hervatten bij terugkeer. Ze zijn echter gemarkeerd als @Deprecated in lifecycle-runtime-ktx 2.6.0, omdat:
repeatOnLifecycle — de door Google aanbevolen manier om coroutines te starten die zijn gesynchroniseerd met de levenscyclus. Het annuleert en herstart de coroutine elke keer wanneer Lifecycle een opgegeven status bereikt.
lifecycleScope.launch {
repeatOnLifecycle(Lifecycle.State.STARTED) {
viewModel.uiState.collect { state ->
updateUI(state)
}
}
}
De coroutine die aan repeatOnLifecycle wordt doorgegeven, start wanneer Lifecycle STARTED bereikt en wordt geannuleerd wanneer het onder STARTED zakt. Bij terugkeer naar STARTED wordt de coroutine opnieuw gestart. Dit is veilig en efficiënt — geen enkele coroutine blijft in pauze hangen.
Voor het verzamelen van gegevens uit Flow met inachtneming van de levenscyclus is er de operator flowWithLifecycle. Deze stopt en hervat automatisch het verzamelen bij verandering van de Lifecycle-status:
viewModel.uiState
.flowWithLifecycle(lifecycle, Lifecycle.State.STARTED)
.onEach { state -> updateUI(state) }
.launchIn(lifecycleScope)
De operator flowWithLifecycle — de meest beknopte manier voor veilig abonneren op Flow in de UI-laag.
Laten we drie realistische scenario's bekijken voor het gebruik van lifecycleScope in een Android-app in 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)
}
}
}
}
}
De coroutine start wanneer het fragment zichtbaar wordt (STARTED) en wordt geannuleerd wanneer het scherm wordt verlaten (STOPPED). Als de gebruiker naar een andere app schakelt, verbruiken locatie-updates geen batterij.
lifecycleScope.launch {
repeatOnLifecycle(Lifecycle.State.RESUMED) {
animateFadeIn(titleView)
delay(200)
animateSlideUp(contentView)
}
}
De animatie start alleen wanneer het fragment op de voorgrond is (RESUMED). Als de gebruiker de app minimaliseert tijdens de animatie, wordt de coroutine geannuleerd en bij terugkeer wordt de animatie opnieuw gestart.
lifecycleScope.launch {
repeatOnLifecycle(Lifecycle.State.STARTED) {
while (isActive) {
syncData()
delay(30_000L)
}
}
}
Gegevens worden elke 30 seconden gesynchroniseerd, maar alleen wanneer het scherm zichtbaar is. isActive controleert of de coroutine niet is geannuleerd, wat een veilige uitgang uit de lus bij het verlaten van het scherm garandeert.
Beide scopes zijn gekoppeld aan de levenscyclus, maar aan verschillende aspecten ervan. Het begrijpen van het verschil is cruciaal voor de juiste architectuur van Android-applicaties.
viewModelScope is gekoppeld aan ViewModel, die schermrotatie overleeft. lifecycleScope is gekoppeld aan LifecycleOwner (Activity/Fragment), die bij rotatie wordt vernietigd en opnieuw aangemaakt. Dit bepaalt de toepassingsscenario's.
In de praktijk komt een combinatie van beide scopes vaak voor: viewModelScope laadt gegevens en beheert de status, lifecycleScope abonneert zich op Flow van ViewModel rekening houdend met de levenscyclus van het scherm. Deze scheiding van verantwoordelijkheden wordt beschouwd als best practice in moderne Android-ontwikkeling.
Laten we vier veelgemaakte fouten bekijken die ontwikkelaars maken bij het gebruik van lifecycleScope.
Als u het laden van gegevens start in lifecycleScope.launch, wordt de coroutine bij schermrotatie geannuleerd en moeten de gegevens opnieuw worden geladen. Gebruik viewModelScope voor langdurige bewerkingen. lifecycleScope — alleen voor UI-gerelateerde taken.
Directe aanroep van viewModel.someFlow.collect { ... } binnen lifecycleScope.launch blijft gegevens verzamelen zelfs wanneer het scherm niet zichtbaar is. Dit kan leiden tot UI-updates op de achtergrond en onnodige overhead. Gebruik altijd repeatOnLifecycle of flowWithLifecycle.
Hoewel lifecycleScope wordt geannuleerd bij DESTROYED, kan code na een suspend-punt mogelijk niet worden uitgevoerd bij plotselinge annulering. Vertrouw niet op uitvoering van code na een suspend-aanroep, tenzij u NonCancellable gebruikt.
launchWhenStarted en zijn analogen annuleren de coroutine niet, maar onderbreken deze alleen. Als het scherm meerdere keren schakelt tussen voor- en achtergrond, accumuleert de coroutine uitgestelde aanroepen. Stap over op repeatOnLifecycle — dit is de enige juiste manier om met Lifecycle te synchroniseren.
Veelgestelde vragen
lifecycleScope wordt automatisch geannuleerd bij vernietiging van LifecycleOwner. GlobalScope leeft gedurende de hele looptijd van de applicatie. Een coroutine in lifecycleScope kan UI niet bijwerken na vernietiging van de component, in GlobalScope kan dat wel, wat leidt tot crashes. Gebruik altijd lifecycleScope in de UI-laag.
Nee, ViewModel is geen LifecycleOwner, dus lifecycleScope is er niet beschikbaar. ViewModel gebruikt viewModelScope. Als code in beide contexten moet worden uitgevoerd — haal de logica dan uit naar use case of repository met suspend-functies.
Elke repeatOnLifecycle-aanroep maakt een nieuwe coroutine aan die het blok start bij het bereiken van de opgegeven Lifecycle-status. Als repeatOnLifecycle tweemaal wordt aangeroepen voor dezelfde status, worden beide blokken onafhankelijk gestart. Meestal is één aanroep in onViewCreated voldoende.
De dispatcher van lifecycleScope kan niet direct worden gewijzigd — het gebruikt Dispatchers.Main.immediate. Binnen het coroutine-blok kunt u via withContext naar een andere dispatcher schakelen. Gebruik voor tests TestDispatcher met LifecycleOwner.
lifecycleScope wordt geannuleerd bij overgang van LifecycleOwner naar de status DESTROYED (na onDestroy). Eenvoudige lifecycleScope.launch-aanroepen worden niet geannuleerd in onPause of onStop. Gebruik voor pauzeren bij overgang naar de achtergrond repeatOnLifecycle(STARTED) of repeatOnLifecycle(RESUMED).
Samenvatting
We ontwikkelen een mobiele applicatie turnkey
IT Sectr creëert sinds 2017 iOS- en Android-applicaties voor startups en bedrijven. We adviseren u en stellen de beste oplossing voor.
Lees ook