App Lifecycle: co to jest, stany aplikacji w iOS i Android

Autor: IT Sectr Opublikowano: 2026-03-02 Czas czytania: 8 min
App Lifecycle (cykl życia aplikacji) — sekwencja stanów, przez które przechodzi aplikacja mobilna od uruchomienia do zakończenia. Zrozumienie lifecycle jest krytyczne dla zarządzania zasobami, zapisywania danych i zapewnienia stabilności. W iOS aplikacja przechodzi przez stany: Not Running → Active → Inactive → Background → Suspended. W Android — przez onCreate → onStart → onResume → onPause → onStop → onDestroy + onRestart. Każdy stan daje programiście okno do zapisania stanu, zwolnienia zasobów lub przygotowania do powrotu. Według danych Apple Documentation, ignorowanie zdarzeń lifecycle jest przyczyną 40% awarii przy zwijaniu aplikacji. W IT Sectr wdrożyliśmy ProcessLifecycleOwner w Android i szablon AppDelegate w iOS jako obowiązkowe standardy dla wszystkich projektów — zmniejszyło to liczbę błędów związanych z tłem o 60%.

Najważniejsze

  • App Lifecycle — zbiór stanów aplikacji: od uruchomienia do zakończenia, każdy z określonymi działaniami programisty.
  • AppDelegate — centralna klasa iOS do obsługi lifecycle: didFinishLaunching, didEnterBackground, willEnterForeground.
  • SceneDelegate — delegat pojedynczej sceny (iOS 13+), zarządzający lifecycle każdego okna w aplikacjach wielookienkowych.
  • ProcessLifecycleOwner — komponent Android z AndroidX Lifecycle, śledzący lifecycle całego procesu.
  • Application.onCreate — pierwszy punkt wejścia aplikacji Android, wywoływany przed dowolną Activity.

Co to jest App Lifecycle?

App Lifecycle — automat stanów opisujący wszystkie możliwe stany aplikacji mobilnej i przejścia między nimi. Każdy stan określa, czy aplikacja może wykonywać kod, wyświetlać UI i zużywać zasoby. iOS i Android mają podobny, ale nie identyczny model — różnice wynikają z architektury systemu: iOS stosuje ścisłą kontrolę pamięci (stan suspended), Android — elastyczne zarządzanie procesami przez onSaveInstanceState.

W iOS lifecycle jest ściśle powiązany z foreground/background: aplikacja jest albo aktywna, albo zawieszona. W Android lifecycle jest bardziej granularny — Activity/Window przechodzi przez 6+ stanów, a sam proces ma dodatkowy lifecycle przez ProcessLifecycleOwner. Nowoczesne aplikacje (od 2024 roku) coraz częściej używają wzorców architektonicznych opartych na lifecycle: SwiftUI Lifecycle (iOS 16+) przez .scenePhase environment, Compose Lifecycle przez LifecycleEventObserver. Te wzorce automatycznie obsługują przełączanie kontekstu i zapobiegają wyciekom pamięci. Według Google, prawidłowa obsługa lifecycle w Android zmniejsza zużycie pamięci o 30–40% podczas pracy w tle.

Cykl życia iOS: AppDelegate i SceneDelegate

W iOS lifecycle aplikacji jest zarządzany przez klasę UIApplicationDelegate (AppDelegate). Główne metody: application(_:didFinishLaunchingWithOptions:) — inicjalizacja przy pierwszym uruchomieniu; applicationDidBecomeActive — aplikacja widoczna i gotowa do interakcji; applicationWillResignActive — przejście w stan nieaktywny (połączenie przychodzące, zamknięcie zasłony); applicationDidEnterBackground — aplikacja ukryta, jest ~5 sekund na zapisanie danych; applicationWillEnterForeground — powrót z tła; applicationWillTerminate — zakończenie (wywoływane tylko dla starych aplikacji bez suspended).

Począwszy od iOS 13, Apple wprowadziło SceneDelegate (UISceneDelegate) do obsługi aplikacji wielookienkowych na iPad i macOS Catalyst. SceneDelegate zarządza lifecycle każdej pojedynczej sceny (okna): scene(_:willConnectTo:options:) — utworzenie sceny; sceneDidBecomeActive — scena aktywna; sceneWillResignActive — scena traci fokus; sceneDidEnterBackground — scena ukryta. AppDelegate odpowiada za zdarzenia globalne (ładowanie danych, push-notifications), a SceneDelegate — za stan UI każdego okna. W SwiftUI lifecycle jest obsługiwany przez wartość środowiska @Environment(\.scenePhase): .active, .inactive, .background — zapewnia to jednolite API dla aplikacji SwiftUI i UIKit.

Cykl życia Android: Application i ProcessLifecycleOwner

W Android lifecycle zaczyna się od klasy Application — singletona, który jest tworzony przed dowolną Activity. Metoda Application.onCreate() — pierwszy punkt wejścia, używany do globalnej inicjalizacji (Analytics, DI, Crash Reporting). Następnie uruchamiana jest Activity z sekwencją: onCreate() → onStart() → onResume(). Przy zwijaniu: onPause() → onStop() → onSaveInstanceState(). Przy zniszczeniu: onDestroy(). Przy powrocie: onRestart() → onStart() → onResume().

ProcessLifecycleOwner (z AndroidX Lifecycle 2.2+) śledzi lifecycle całego procesu, a nie pojedynczej Activity. Zapewnia dwa stany: ON_RESUME (aplikacja w foreground) i ON_STOP (aplikacja ukryta). ProcessLifecycleOwner rozwiązuje problem "kiedy aplikacja poszła w tło" na poziomie procesu — jest to krytyczne dla SDK, bibliotek i aplikacji modułowych. W Jetpack Compose lifecycle jest zarządzany przez LifecycleEventObserver i collectAsStateWithLifecycle, który automatycznie wstrzymuje zbieranie danych w trybie tła. Android 14 (API 34) dodał powiadomienie o foreground service lifecycle przez Service.onTimeout — usługa musi zakończyć się w ciągu 6 godzin, w przeciwnym razie system zatrzymuje ją przymusowo.

Porównanie lifecycle iOS i Android

iOS Android Opis
Not Running — Aplikacja nie jest uruchomiona
didFinishLaunching Application.onCreate Pierwsza inicjalizacja przy uruchomieniu
Active onResume Aplikacja widoczna i przyjmuje dane wejściowe
Inactive onPause Przejściowa utrata fokusu (połączenie, zasłona)
Background onStop Aplikacja ukryta, kod może być wykonywany
Suspended — Kod nie jest wykonywany, pamięć zarezerwowana
Will Terminate onDestroy Aplikacja jest zamykana

Główna różnica: iOS przymusowo przełącza aplikację w stan Suspended (kod nie jest wykonywany) po 5-10 sekundach od przejścia w tło. Android pozwala na pracę w tle (usługi, WorkManager) przez dłuższy czas, ale z ograniczeniami Doze Mode (Android 6+) i ograniczeniami tła (Android 12+). ProcessLifecycleOwner w Android — odpowiednik UIApplicationDidEnterBackgroundNotification w iOS z tą różnicą, że wyzwala się przy każdym przejściu w tło, a nie tylko po utracie fokusu.

Przykłady kodu

iOS: AppDelegate z metodami lifecycle

Podstawowa implementacja AppDelegate z obsługą wszystkich stanów cyklu życia. Zapisywanie danych przy przejściu w tło i aktualizacja UI przy powrocie.

swift
import UIKit

@main
class AppDelegate: UIResponder, UIApplicationDelegate {

    func application(
        _ application: UIApplication,
        didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
    ) -> Bool {
        Analytics.shared.initialize()
        return true
    }

    func applicationDidBecomeActive(_ application: UIApplication) {
        NotificationCenter.default.post(name: .appDidBecomeActive, object: nil)
    }

    func applicationWillResignActive(_ application: UIApplication) {
        NotificationCenter.default.post(name: .appWillResignActive, object: nil)
    }

    func applicationDidEnterBackground(_ application: UIApplication) {
        CoreDataManager.shared.saveContext()
        UserDefaults.standard.synchronize()
    }

    func applicationWillEnterForeground(_ application: UIApplication) {
        NetworkManager.shared.refreshSession()
    }
}

AppDelegate — centralny punkt lifecycle. applicationDidEnterBackground — krytyczna metoda: iOS daje ~5 sekund na zapisanie danych. applicationDidBecomeActive — zaktualizuj UI, uruchom ponownie animacje. Dla SceneDelegate (iOS 13+) logika lifecycle jest rozdzielona na sceny: sceneDidBecomeActive / sceneDidEnterBackground zarządzają poszczególnymi oknami.

iOS: SceneDelegate (iOS 13+)

SceneDelegate dla aplikacji wielookienkowych iPad. Każda scena ma własny lifecycle, niezależny od innych okien.

swift
import UIKit

class SceneDelegate: UIResponder, UIWindowSceneDelegate {

    var window: UIWindow?

    func scene(
        _ scene: UIScene,
        willConnectTo session: UISceneSession,
        options connectionOptions: UIScene.ConnectionOptions
    ) {
        guard let windowScene = (scene as? UIWindowScene) else { return }
        window = UIWindow(windowScene: windowScene)
        window?.rootViewController = ViewController()
        window?.makeKeyAndVisible()
    }

    func sceneDidBecomeActive(_ scene: UIScene) {
        PlayerManager.shared.resume()
    }

    func sceneDidEnterBackground(_ scene: UIScene) {
        PlayerManager.shared.pause()
        CoreDataManager.shared.saveContext()
    }

    func sceneDidDisconnect(_ scene: UIScene) {
        PlayerManager.shared.cleanup()
    }
}

SceneDelegate zarządza lifecycle pojedynczej sceny. sceneDidBecomeActive / sceneDidEnterBackground — odpowiednik metod AppDelegate dla konkretnego okna. sceneDidDisconnect jest wywoływane przy zamknięciu sceny (użytkownik zamknął okno na iPad). Dla zachowania zgodności z iOS 12 i starszymi, AppDelegate powinien dublować logikę SceneDelegate. W iOS 17+ można użyć @Observable do automatycznego wstrzymywania/wznawiania zadań na podstawie scenePhase.

Android: Application z ProcessLifecycleOwner

ProcessLifecycleOwner śledzi, kiedy aplikacja znajduje się w foreground/background na poziomie procesu. Jest to optymalny sposób globalnego zarządzania lifecycle.

kotlin
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 — jedyny poprawny sposób śledzenia przejścia w tło na poziomie aplikacji. ON_START wyzwala się, gdy aplikacja staje się widoczna (foreground), ON_STOP — gdy jest całkowicie ukryta (background). W przeciwieństwie do Activity lifecycle, ProcessLifecycleOwner nie jest powiązany z konkretnym ekranem. Dla Jetpack Compose używaj LifecycleResumeEffect lub collectAsStateWithLifecycle zamiast ręcznego obserwowania.

Android: Activity Lifecycle z ViewModel

ViewModel + Lifecycle — prawidłowa architektura Android do pracy z lifecycle. ViewModel automatycznie czyści się przy onDestroy, zapobiegając wyciekom.

kotlin
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 — zwalnianie zasobów")
    }
}

// W 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 — wstrzymanie animacji")
    }

    override fun onDestroy() {
        super.onDestroy()
        Logger.d("Activity destroyed — czyszczenie")
    }
}

ViewModel przetrwa obrót ekranu i jest niszczony tylko przy finish() Activity. onCleared() — miejsce do zwalniania zasobów, wypisywania się ze strumieni. LiveData automatycznie wstrzymuje obserwację przy onPause i wznawia przy onResume — zapewnia to ochronę przed wyciekami i awariami podczas pracy w tle. W Compose używaj collectAsStateWithLifecycle() do tego samego celu.

Często zadawane pytania

Co się dzieje, gdy użytkownik zwija aplikację iOS?

Podczas zwijania aplikacja przechodzi z active do inactive (krótkotrwale), następnie do background. Po kilku sekundach system może przełączyć ją w suspended — kod nie jest wykonywany, pamięć jest zarezerwowana. Przy braku pamięci suspended-aplikacja jest terminowana (willTerminate nie jest wywoływane). Zapisz dane w applicationDidEnterBackground — to ostatni gwarantowany punkt do zapisu.

Czy trzeba obsługiwać wszystkie stany App Lifecycle?

Minimalnie obowiązkowe: applicationDidEnterBackground — zapisz dane użytkownika; applicationWillEnterForeground — zaktualizuj UI; w Android onPause — wstrzymaj animacje/czujniki. ProcessLifecycleOwner upraszcza obsługę: onResume — onPause dla foreground, onStart — onStop dla widoczności. Pozostałe stany obsługuj w miarę potrzeb — nie wszystkie stany są krytyczne dla każdej aplikacji.

Czym SceneDelegate różni się od AppDelegate?

AppDelegate — globalny delegat całej aplikacji (uruchomienie, przejście w tło). SceneDelegate (iOS 13+) zarządza lifecycle pojedynczego okna (sceny) — w wielookienkowych aplikacjach iPad każda scena ma własny lifecycle. Dla iOS 12 i starszych cały lifecycle jest obsługiwany przez AppDelegate. Od iPadOS 16+ SceneDelegate jest obowiązkowy dla Stage Manager.

Czym jest ProcessLifecycleOwner w Android?

ProcessLifecycleOwner — komponent z AndroidX Lifecycle, który śledzi lifecycle całej aplikacji (procesu), a nie pojedynczej Activity. Zapewnia dwa główne zdarzenia: ON_RESUME (aplikacja w foreground) i ON_STOP (aplikacja w background). Jest używany do inicjalizacji/czyszczenia SDK, analityki, monitorów sieciowych — wszystkiego, co powinno reagować na przejście aplikacji w tło, niezależnie od bieżącego ekranu.

Jak obsługiwać lifecycle w Jetpack Compose?

W Jetpack Compose używaj LifecycleEventObserver przez LocalLifecycleOwner.current.lifecycle lub funkcji collectAsStateWithLifecycle(). Dla ekranów Compose stosuj LifecycleResumeEffect — odpowiednik DisposableEffect, który uruchamia się przy onResume i czyści przy onPause. lifecycleScope.launchWhenResumed — corutina automatycznie wstrzymywana w tle.

Podsumowanie

  • App Lifecycle — automat stanów aplikacji określający zarządzanie zasobami, zapisywanie danych i stabilność.
  • iOS AppDelegate (applicationDidEnterBackground) — krytyczna metoda do zapisywania danych przy przejściu w tło w ciągu 5 sekund.
  • iOS SceneDelegate (iOS 13+) zarządza lifecycle każdej sceny oddzielnie — obowiązkowy dla wielookienkowych aplikacji iPad.
  • Android ProcessLifecycleOwner — globalny obserwator lifecycle procesu do inicjalizacji/czyszczenia SDK.
  • ViewModel w Android przetrwa obrót ekranu i jest czyszczony przy finish Activity — zapobiega wyciekom pamięci.
  • SwiftUI @Environment(\.scenePhase) — jednolite API dla lifecycle w SwiftUI (active, inactive, background).
  • Prawidłowa obsługa lifecycle zmniejsza zużycie pamięci o 30-40% i zapobiega 40% awarii podczas pracy w tle.

Opracujemy aplikację mobilną pod klucz

IT Sectr tworzy aplikacje na iOS i Androida dla startupów i firm od 2017 roku. Doradzimy Ci i zaproponujemy najlepsze rozwiązanie.

Omów projekt

Przeczytaj również