Hlavní body
App Lifecycle — konečný automat popisující všechny možné stavy mobilní aplikace a přechody mezi nimi. Každý stav určuje, zda aplikace může vykonávat kód, zobrazovat UI a spotřebovávat zdroje. iOS a Android mají podobný, ale ne identický model — rozdíly vyplývají z architektury OS: iOS používá přísnou kontrolu paměti (stav suspended), Android — flexibilní správu procesů přes onSaveInstanceState.
V iOS je lifecycle pevně svázán s foreground/background: aplikace je buď aktivní, nebo pozastavena. V Android je lifecycle více granulární — Activity/Window prochází 6+ stavy a samotný proces má další lifecycle přes ProcessLifecycleOwner. Moderní aplikace (od 2024) stále častěji používají architektonické vzory založené na lifecycle: SwiftUI Lifecycle (iOS 16+) přes .scenePhase environment, Compose Lifecycle přes LifecycleEventObserver. Tyto vzory automaticky zpracovávají přepínání kontextu a zabraňují únikům paměti. Podle Google správné zpracování lifecycle v Android snižuje spotřebu paměti o 30–40% při práci na pozadí.
V iOS je lifecycle aplikace spravován přes třídu UIApplicationDelegate (AppDelegate). Hlavní metody: application(_:didFinishLaunchingWithOptions:) — inicializace při prvním spuštění; applicationDidBecomeActive — aplikace viditelná a připravená k interakci; applicationWillResignActive — přechod do neaktivního stavu (příchozí hovor, zavření závěsu); applicationDidEnterBackground — aplikace skrytá, je ~5 sekund na uložení dat; applicationWillEnterForeground — návrat z pozadí; applicationWillTerminate — ukončení (volá se pouze pro staré aplikace bez suspended).
Od iOS 13 Apple zavedl SceneDelegate (UISceneDelegate) pro podporu aplikací s více okny na iPad a macOS Catalyst. SceneDelegate spravuje lifecycle každé jednotlivé scény (okna): scene(_:willConnectTo:options:) — vytvoření scény; sceneDidBecomeActive — scéna aktivní; sceneWillResignActive — scéna ztrácí fokus; sceneDidEnterBackground — scéna skrytá. AppDelegate odpovídá za globální události (načítání dat, push notifikace) a SceneDelegate — za stav UI každého okna. V SwiftUI je lifecycle spravován přes environment hodnotu @Environment(\.scenePhase): .active, .inactive, .background — to poskytuje jednotné API pro SwiftUI a UIKit aplikace.
V Android lifecycle začíná třídou Application — singletonem, který je vytvořen před jakoukoliv Activity. Metoda Application.onCreate() — první vstupní bod, používaný pro globální inicializaci (Analytics, DI, Crash Reporting). Poté je Activity spuštěna s posloupností: onCreate() → onStart() → onResume(). Při minimalizaci: onPause() → onStop() → onSaveInstanceState(). Při zničení: onDestroy(). Při návratu: onRestart() → onStart() → onResume().
ProcessLifecycleOwner (z AndroidX Lifecycle 2.2+) sleduje lifecycle celého procesu, nikoli jednotlivé Activity. Poskytuje dva stavy: ON_RESUME (aplikace v foreground) a ON_STOP (aplikace skrytá). ProcessLifecycleOwner řeší problém "kdy aplikace přešla na pozadí" na úrovni procesu — to je kritické pro SDK, knihovny a modulární aplikace. V Jetpack Compose je lifecycle spravován přes LifecycleEventObserver a collectAsStateWithLifecycle, který automaticky pozastavuje sběr dat v režimu pozadí. Android 14 (API 34) přidal oznámení o foreground service lifecycle přes Service.onTimeout — služba musí skončit do 6 hodin, jinak ji systém vynuceně zastaví.
| iOS | Android | Popis |
|---|---|---|
| Not Running | — | Aplikace není spuštěna |
| didFinishLaunching | Application.onCreate | První inicializace při spuštění |
| Active | onResume | Aplikace viditelná a přijímá vstup |
| Inactive | onPause | Dočasná ztráta fokusu (hovor, závěs) |
| Background | onStop | Aplikace skrytá, kód může být vykonáván |
| Suspended | — | Kód se nevykonává, paměť rezervována |
| Will Terminate | onDestroy | Aplikace se ukončuje |
Hlavní rozdíl: iOS vynuceně převádí aplikaci do Suspended (kód se nevykonává) 5-10 sekund po přechodu na pozadí. Android povoluje práci na pozadí (služby, WorkManager) po delší dobu, ale s omezeními Doze Mode (Android 6+) a omezeními pozadí (Android 12+). ProcessLifecycleOwner v Android — analog UIApplicationDidEnterBackgroundNotification v iOS s tím rozdílem, že se aktivuje při každém přechodu na pozadí, nejen po ztrátě fokusu.
Základní implementace AppDelegate se zpracováním všech stavů životního cyklu. Ukládání dat při přechodu na pozadí a aktualizace UI při návratu.
import UIKit
@main
class AppDelegate: UIResponder, UIApplicationDelegate {
func application(_: UIApplication, didFinishLaunchingWithOptions lo: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { Analytics.shared.initialize(); return true }
func applicationDidBecomeActive(_: UIApplication) { NotificationCenter.default.post(name: .appDidBecomeActive, object: nil) }
func applicationWillResignActive(_: UIApplication) { NotificationCenter.default.post(name: .appWillResignActive, object: nil) }
func applicationDidEnterBackground(_: UIApplication) { CoreDataManager.shared.saveContext(); UserDefaults.standard.synchronize() }
func applicationWillEnterForeground(_: UIApplication) { NetworkManager.shared.refreshSession() }
}AppDelegate — centrální bod lifecycle. applicationDidEnterBackground — kritická metoda: iOS dává ~5 sekund na uložení dat. applicationDidBecomeActive — aktualizujte UI, restartujte animace. Pro SceneDelegate (iOS 13+) je logika lifecycle rozdělena na scény: sceneDidBecomeActive / sceneDidEnterBackground spravují jednotlivá okna.
SceneDelegate pro aplikace s více okny na iPad. Každá scéna má vlastní lifecycle, nezávislý na ostatních oknech.
import UIKit
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
var window: UIWindow?
func scene(_: UIScene, willConnectTo s: UISceneSession, options o: UIScene.ConnectionOptions) {
guard let ws = (_ as? UIWindowScene) else { return }
window = UIWindow(windowScene: ws)
window?.rootViewController = ViewController()
window?.makeKeyAndVisible()
}
func sceneDidBecomeActive(_: UIScene) { PlayerManager.shared.resume() }
func sceneDidEnterBackground(_: UIScene) { PlayerManager.shared.pause(); CoreDataManager.shared.saveContext() }
func sceneDidDisconnect(_: UIScene) { PlayerManager.shared.cleanup() }
}SceneDelegate spravuje lifecycle jednotlivé scény. sceneDidBecomeActive / sceneDidEnterBackground — ekvivalent metod AppDelegate pro konkrétní okno. sceneDidDisconnect se volá při zavření scény (uživatel zavřel okno na iPad). Pro zachování kompatibility s iOS 12 a nižším musí AppDelegate duplikovat logiku SceneDelegate. V iOS 17+ můžete použít @Observable pro automatické pozastavení/obnovení úkolů na základě scenePhase.
ProcessLifecycleOwner sleduje, kdy je aplikace v foreground/background na úrovni procesu. To je optimální způsob globální správy lifecycle.
import android.app.Application
import androidx.lifecycle.ProcessLifecycleOwner
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleObserver
import androidx.lifecycle.OnLifecycleEvent
class MainApplication : Application() {
override fun onCreate() { super.onCreate(); ProcessLifecycleOwner.get().lifecycle.addObserver(AppLifecycleObserver()) }
}
class AppLifecycleObserver : LifecycleObserver {
@OnLifecycleEvent(Lifecycle.Event.ON_START) fun onEnterForeground() { Analytics.shared.onForeground(); NetworkMonitor.shared.start() }
@OnLifecycleEvent(Lifecycle.Event.ON_STOP) fun onEnterBackground() { Analytics.shared.onBackground(); NetworkMonitor.shared.stop() }
}ProcessLifecycleOwner — jediný správný způsob sledování přechodu na pozadí na úrovni aplikace. ON_START se aktivuje, když se aplikace stane viditelnou (foreground), ON_STOP — když je zcela skryta (background). Na rozdíl od Activity lifecycle, ProcessLifecycleOwner není vázán na konkrétní obrazovku. Pro Jetpack Compose použijte LifecycleResumeEffect nebo collectAsStateWithLifecycle místo ručního pozorování.
ViewModel + Lifecycle — správná Android architektura pro práci s lifecycle. ViewModel se automaticky čistí při onDestroy, zabraňuje únikům paměti.
import androidx.lifecycle.ViewModel
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
class TimerViewModel : ViewModel() {
private val _time = MutableLiveData<Long>()
val time: LiveData<Long> = _time
private var startTime = System.currentTimeMillis()
init { updateTime() }
private fun updateTime() { _time.value = System.currentTimeMillis() - startTime }
override fun onCleared() { super.onCleared(); Logger.d("ViewModel cleared — uvolnění zdrojů") }
}
// V Activity
class TimerActivity : AppCompatActivity() {
private val viewModel: TimerViewModel by viewModels()
override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState); Logger.d("Activity created") }
override fun onResume() { super.onResume(); viewModel.time.observe(this) { Logger.d("Time: $it") } }
override fun onPause() { super.onPause(); Logger.d("Activity paused — pozastavení animací") }
override fun onDestroy() { super.onDestroy(); Logger.d("Activity destroyed — čištění") }
}ViewModel přežije otočení obrazovky a je zničen pouze při finish() Activity. onCleared() — místo pro uvolnění zdrojů, odhlášení z datových proudů. LiveData automaticky pozastavuje pozorování při onPause a obnovuje při onResume — poskytuje ochranu před úniky a pády během práce na pozadí. V Compose použijte collectAsStateWithLifecycle() pro stejný účel.
Často kladené otázky
Při minimalizaci aplikace přechází z active do inactive (krátce), poté do background. Po několika sekundách ji systém může převést do suspended — kód se nevykonává, paměť je rezervována. Při nedostatku paměti je suspended aplikace ukončena (willTerminate se nevolá). Ukládejte data v applicationDidEnterBackground — to je poslední garantovaný bod pro uložení.
Minimálně povinné: applicationDidEnterBackground — uložte uživatelská data; applicationWillEnterForeground — aktualizujte UI; v Android onPause — pozastavte animace/senzory. ProcessLifecycleOwner zjednodušuje zpracování: onResume — onPause pro foreground, onStart — onStop pro viditelnost. Ostatní stavy zpracovávejte podle potřeby — ne všechny stavy jsou kritické pro každou aplikaci.
AppDelegate — globální delegát celé aplikace (spuštění, přechod na pozadí). SceneDelegate (iOS 13+) spravuje lifecycle jednotlivého okna (scény) — v aplikacích s více okny na iPad má každá scéna vlastní lifecycle. Pro iOS 12 a nižší je celý lifecycle zpracováván přes AppDelegate. Od iPadOS 16+ je SceneDelegate povinný pro Stage Manager.
ProcessLifecycleOwner — komponent z AndroidX Lifecycle, který sleduje lifecycle celé aplikace (procesu), nikoli jednotlivé Activity. Poskytuje dvě hlavní události: ON_RESUME (aplikace v foreground) a ON_STOP (aplikace v background). Používá se pro inicializaci/čištění SDK, analytiky, síťových monitorů — všeho, co by mělo reagovat na přechod aplikace na pozadí, bez ohledu na aktuální obrazovku.
V Jetpack Compose použijte LifecycleEventObserver přes LocalLifecycleOwner.current.lifecycle nebo funkci collectAsStateWithLifecycle(). Pro Compose obrazovky aplikujte LifecycleResumeEffect — analog DisposableEffect, který se spouští při onResume a čistí při onPause. lifecycleScope.launchWhenResumed — korutina automaticky pozastavená na pozadí.
Shrnutí
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í.
Přečtěte si také