lifecycleScope — co to je, propojení s Lifecycle a práce v Androidu

Autor: IT Sectr Publikováno: 2026-06-23 Doba čtení: 9 min

lifecycleScope — je vestavěný CoroutineScope z knihovny androidx.lifecycle, který je připojen k životnímu cyklu Activity, Fragment nebo jakéhokoli LifecycleOwner a automaticky ruší korutiny při zničení komponenty. Podle Google Android Developers, 2025 umožňuje lifecycleScope bezpečně spouštět korutiny spojené s vrstvou UI bez rizika provedení kódu po zničení Activity nebo Fragmentu. Scope se automaticky zruší při přechodu LifecycleOwner do stavu DESTROYED.

Hlavní body

  • lifecycleScope — CoroutineScope z lifecycle-runtime-ktx, rušený při stavu DESTROYED Lifecycle
  • lifecycleScope.launch — spuštění korutiny, která se automaticky zruší při zničení LifecycleOwner
  • launchWhenStarted / launchWhenResumed — zastaralé metody, nahrazené repeatOnLifecycle
  • repeatOnLifecycle — moderní API pro spouštění korutin sledujících konkrétní stav Lifecycle
  • Dispatchers.Main.immediate — výchozí dispečer pro lifecycleScope

Co je lifecycleScope v Androidu?

lifecycleScope — je rozšiřující vlastnost na rozhraní LifecycleOwner (Activity, Fragment, Service), která poskytuje hotový CoroutineScope připojený k plnému životnímu cyklu komponenty. Když LifecycleOwner dosáhne stavu DESTROYED, lifecycleScope automaticky zruší všechny aktivní korutiny.

kotlin
// Ve Fragment nebo Activity
lifecycleScope.launch {
    delay(1000)
    showSnackbar("Ahoj!")
}

Na rozdíl od viewModelScope se lifecycleScope ruší při každém zničení LifecycleOwner — včetně rotace obrazovky. To jej činí ideálním pro operace, které by měly žít pouze dokud je konkrétní obrazovka viditelná.

Kde je lifecycleScope dostupný

lifecycleScope je dostupný všude tam, kde je LifecycleOwner:

  • Activity — AppCompatActivity dědí LifecycleOwner
  • Fragment — Fragment dědí LifecycleOwner
  • LifecycleService — služba s životním cyklem
  • ProcessLifecycleOwner — životní cyklus celé aplikace
  • Vlastní LifecycleOwner — jakékoli objekty implementující LifecycleOwner

Jak funguje lifecycleScope: Lifecycle a automatické zrušení

Mechanismus automatického rušení lifecycleScope je založen na odběru událostí Lifecycle. Když Lifecycle klesne pod CREATED do DESTROYED, scope je zrušen.

Stavy Lifecycle

StavPopisScope aktivní
CREATEDLifecycleOwner vytvořen, onCreate provedenAno
STARTEDLifecycleOwner viditelný (onStart)Ano
RESUMEDLifecycleOwner v popředí (onResume)Ano
DESTROYEDLifecycleOwner zničen (onDestroy)Ne (scope zrušen)

Vnitřní struktura lifecycleScope

lifecycleScope je vytvořen jako CoroutineScope(SupervisorJob() + Dispatchers.Main.immediate) a uložen uvnitř Lifecycle. Při přechodu Lifecycle do stavu DESTROYED je voláno scope.cancel(). Mechanismus je implementován prostřednictvím LifecycleEventObserver, který se přihlásí k odběru událostí životního cyklu při prvním přístupu ke scope.

Chování při rotaci

Při rotaci obrazovky je Activity zničeno (onDestroy) a znovu vytvořeno. lifecycleScope je zrušen spolu se starou Activity a pro novou Activity je vytvořena nová instance scope. To je zásadní rozdíl oproti viewModelScope, který je při rotaci zachován.

API lifecycleScope: launch, launchWhen a repeatOnLifecycle

Knihovna lifecycle poskytuje několik způsobů spouštění korutin prostřednictvím lifecycleScope. Podívejme se na vývoj API od zastaralých metod k moderním.

lifecycleScope.launch — základní spuštění

Nejjednodušší způsob — lifecycleScope.launch { ... }. Korutina se spustí okamžitě a zruší se při DESTROYED. Může však vykonávat kód i když UI není viditelné (např. na pozadí po onStop). To není vždy žádoucí.

Zastaralé: launchWhenCreated / launchWhenStarted / launchWhenResumed

Tyto metody pozastavovaly provádění korutiny, když Lifecycle klesl pod určený stav, a obnovovaly při návratu. Byly však označeny jako @Deprecated v lifecycle-runtime-ktx 2.6.0, protože:

  • Korutinu nerušily — pouze ji pozastavovaly
  • Vedly k hromadění visících korutin spotřebovávajících paměť
  • Vytvářely race condition při rychlém přepínání stavů

Moderní API: repeatOnLifecycle

repeatOnLifecycle — doporučený způsob Google pro spouštění korutin synchronizovaných s životním cyklem. Ruší a restartuje korutinu pokaždé, když Lifecycle dosáhne určeného stavu.

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

Korutina předaná do repeatOnLifecycle se spustí když Lifecycle dosáhne STARTED a zruší se když klesne pod STARTED. Při návratu do STARTED se korutina restartuje od začátku. To je bezpečné a efektivní — žádné korutiny nevisí v pauze.

flowWithLifecycle — pro Flow

Pro sběr dat z Flow s ohledem na životní cyklus existuje operátor flowWithLifecycle. Automaticky zastavuje a obnovuje sběr při změně stavu Lifecycle:

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

Operátor flowWithLifecycle — nejstručnější způsob bezpečného odběru Flow ve vrstvě UI.

Příklady použití lifecycleScope

Podívejme se na tři reálné scénáře použití lifecycleScope v Android aplikaci v Kotlin.

Příklad 1: Odběr aktualizací polohy pouze když je obrazovka viditelná

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)
                }
            }
        }
    }
}

Korutina startuje když se fragment stane viditelným (STARTED) a ruší se když opustí obrazovku (STOPPED). Pokud uživatel přepne na jinou aplikaci, aktualizace polohy nespotřebovávají baterii.

Příklad 2: Spuštění animace při startu fragmentu

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

Animace se spouští pouze když je fragment v popředí (RESUMED). Pokud uživatel minimalizuje aplikaci během animace, korutina je zrušena a při návratu se animace spustí znovu.

Příklad 3: Periodická synchronizace dat na viditelné obrazovce

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

Data jsou synchronizována každých 30 sekund, ale pouze když je obrazovka viditelná. isActive kontroluje, zda korutina nebyla zrušena, což zajišťuje bezpečný výstup z cyklu při opuštění obrazovky.

lifecycleScope vs viewModelScope: scénáře použití

Oba scopes jsou připojeny k životnímu cyklu, ale k jeho různým aspektům. Pochopení rozdílu je kritické pro správnou architekturu Android aplikací.

Klíčový rozdíl

viewModelScope je připojen k ViewModel, který přežije rotaci obrazovky. lifecycleScope je připojen k LifecycleOwner (Activity/Fragment), který se při rotaci ničí a znovu vytváří. To určuje scénáře jejich použití.

Kdy použít lifecycleScope

  • Odběr systémových událostí (poloha, senzory, kamera)
  • Animace a UI efekty připojené ke konkrétní obrazovce
  • Dávkové načítání dat s ohledem na viditelnost obrazovky
  • Operace, které by měly skončit při opuštění obrazovky

Kdy použít viewModelScope

  • Načítání dat z Repository
  • Obchodní logika, která by měla přežít rotaci
  • Kešování a zpracování dat
  • Jakékoli operace, jejichž výsledek je potřeba po rotaci

Kombinované použití

V praxi se často setkáváme s kombinací obou scope: viewModelScope načítá data a spravuje stav, lifecycleScope odebírá Flow z ViewModel s ohledem na životní cyklus obrazovky. Toto rozdělení odpovědnosti je považováno za best practice v moderním Android vývoji.

Typické chyby při práci s lifecycleScope

Podívejme se na čtyři nejčastější chyby, kterých se vývojáři dopouštějí při používání lifecycleScope.

Chyba 1: Použití lifecycleScope místo viewModelScope pro načítání dat

Pokud spustíte načítání dat v lifecycleScope.launch, při rotaci obrazovky dojde ke zrušení korutiny a data bude nutné načíst znovu. Používejte viewModelScope pro dlouhotrvající operace. lifecycleScope — pouze pro úkoly související s UI.

Chyba 2: Sběr Flow bez repeatOnLifecycle

Přímé volání viewModel.someFlow.collect { ... } uvnitř lifecycleScope.launch pokračuje ve sběru dat i když obrazovka není viditelná. To může vést k aktualizacím UI na pozadí a zbytečné režii. Vždy používejte repeatOnLifecycle nebo flowWithLifecycle.

Chyba 3: Zapomenutí na zrušení při opuštění obrazovky

Ačkoli se lifecycleScope ruší při DESTROYED, kód po bodu pozastavení (suspend) se nemusí provést při náhlém zrušení. Nespoléhejte na provedení kódu po volání suspend, pokud nepoužíváte NonCancellable.

Chyba 4: Použití zastaralého launchWhenStarted místo repeatOnLifecycle

launchWhenStarted a jeho analogy korutinu neruší, pouze ji pozastavují. Pokud obrazovka mnohokrát přepíná mezi popředím a pozadím, korutina hromadí odložená volání. Přepněte na repeatOnLifecycle — to je jediný správný způsob synchronizace s Lifecycle.

Často kladené otázky

Jaký je rozdíl mezi lifecycleScope a GlobalScope?

lifecycleScope se automaticky ruší při zničení LifecycleOwner. GlobalScope žije po celou dobu běhu aplikace. Korutina v lifecycleScope nemůže aktualizovat UI po zničení komponenty, v GlobalScope může, což vede k pádům. Vždy používejte lifecycleScope ve vrstvě UI.

Lze použít lifecycleScope ve ViewModel?

Ne, ViewModel není LifecycleOwner, takže lifecycleScope v něm není dostupný. ViewModel používá viewModelScope. Pokud má být kód spouštěn v obou kontextech — vyčleňte logiku do use case nebo repository se suspend funkcemi.

Co se stane při opakovaném volání repeatOnLifecycle?

Každé volání repeatOnLifecycle vytváří novou korutinu, která spouští blok při dosažení určeného stavu Lifecycle. Pokud je repeatOnLifecycle volán dvakrát pro stejný stav, oba bloky poběží nezávisle. Obvykle stačí jedno volání v onViewCreated.

Lze nastavit vlastní Dispatcher pro lifecycleScope?

Přímo změnit dispečer lifecycleScope nelze — používá Dispatchers.Main.immediate. Uvnitř bloku korutiny se můžete přepnout na jiný dispečer pomocí withContext. Pro testy používejte TestDispatcher s LifecycleOwner.

Ruší se lifecycleScope v onPause nebo onDestroy?

lifecycleScope se ruší při přechodu LifecycleOwner do stavu DESTROYED (po onDestroy). Jednoduchá volání lifecycleScope.launch se neruší v onPause nebo onStop. Pro pozastavení při přechodu na pozadí použijte repeatOnLifecycle(STARTED) nebo repeatOnLifecycle(RESUMED).

Shrnutí

  • lifecycleScope — CoroutineScope připojený k LifecycleOwner, automaticky rušený při DESTROYED prostřednictvím LifecycleEventObserver
  • Dispatchers.Main.immediate — výchozí dispečer zajišťující bezpečnou aktualizaci UI bez zbytečných přepnutí
  • repeatOnLifecycle — moderní API pro spouštění korutin v určeném stavu Lifecycle s automatickým rušením a restartem
  • flowWithLifecycle — operátor pro bezpečný sběr Flow z UI s ohledem na životní cyklus
  • launchWhenStarted je zastaralý — místo pozastavení používejte repeatOnLifecycle, který korutinu ruší, nikoli pozastavuje
  • lifecycleScope vs viewModelScope — lifecycleScope pro UI operace (animace, poloha), viewModelScope pro data a obchodní logiku
  • Rotace obrazovky — lifecycleScope se ruší při rotaci, viewModelScope je zachován; vybírejte scope podle úkolu

Vyvineme mobilní aplikaci na klíč

IT Sectr vytváří aplikace pro iOS a Android pro startupy a podniky od roku 2017. Poradíme vám a navrhneme nejlepší řešení.

Prodiskutovat projekt

Přečtěte si také