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ż