Belangrijkste punten
App Lifecycle — een eindige automaat die alle mogelijke toestanden van een mobiele app en de overgangen ertussen beschrijft. Elke toestand bepaalt of de app code kan uitvoeren, UI kan weergeven en resources kan verbruiken. iOS en Android hebben een vergelijkbaar maar niet identiek model — de verschillen komen voort uit de OS-architectuur: iOS gebruikt strikt geheugenbeheer (suspended-toestand), Android — flexibel procesbeheer via onSaveInstanceState.
In iOS is de lifecycle sterk gekoppeld aan foreground/background: de app is ofwel actief ofwel geschorst. In Android is de lifecycle granulairder — Activity/Window doorloopt 6+ toestanden en het proces zelf heeft een extra lifecycle via ProcessLifecycleOwner. Moderne apps (vanaf 2024) gebruiken steeds vaker architectuurpatronen op basis van lifecycle: SwiftUI Lifecycle (iOS 16+) via .scenePhase environment, Compose Lifecycle via LifecycleEventObserver. Deze patronen verwerken contextwisselingen automatisch en voorkomen geheugenlekken. Volgens Google vermindert correcte lifecycle-verwerking in Android het geheugengebruik met 30–40% tijdens achtergrondwerk.
In iOS wordt de app-lifecycle beheerd via de klasse UIApplicationDelegate (AppDelegate). Belangrijkste methoden: application(_:didFinishLaunchingWithOptions:) — initialisatie bij eerste start; applicationDidBecomeActive — app zichtbaar en klaar voor interactie; applicationWillResignActive — overgang naar inactieve toestand (inkomende oproep, sluiten gordijn); applicationDidEnterBackground — app verborgen, ~5 seconden om gegevens op te slaan; applicationWillEnterForeground — terugkeer uit achtergrond; applicationWillTerminate — beëindiging (alleen aangeroepen voor oude apps zonder suspended).
Vanaf iOS 13 introduceerde Apple SceneDelegate (UISceneDelegate) voor ondersteuning van multi-venster apps op iPad en macOS Catalyst. SceneDelegate beheert de lifecycle van elke afzonderlijke scene (venster): scene(_:willConnectTo:options:) — aanmaken scene; sceneDidBecomeActive — scene actief; sceneWillResignActive — scene verliest focus; sceneDidEnterBackground — scene verborgen. AppDelegate is verantwoordelijk voor globale gebeurtenissen (gegevens laden, pushmeldingen), SceneDelegate — voor de UI-status van elk venster. In SwiftUI wordt de lifecycle beheerd via de environment-waarde @Environment(\.scenePhase): .active, .inactive, .background — dit biedt een uniforme API voor SwiftUI- en UIKit-apps.
In Android begint de lifecycle met de klasse Application — een singleton die vóór elke Activity wordt aangemaakt. De methode Application.onCreate() — eerste toegangspunt, gebruikt voor globale initialisatie (Analytics, DI, Crash Reporting). Daarna wordt Activity gestart met de reeks: onCreate() → onStart() → onResume(). Bij minimaliseren: onPause() → onStop() → onSaveInstanceState(). Bij vernietiging: onDestroy(). Bij terugkeer: onRestart() → onStart() → onResume().
ProcessLifecycleOwner (van AndroidX Lifecycle 2.2+) volgt de lifecycle van het hele proces, niet van een afzonderlijke Activity. Biedt twee toestanden: ON_RESUME (app in foreground) en ON_STOP (app verborgen). ProcessLifecycleOwner lost het probleem "wanneer ging de app naar de achtergrond" op procesniveau op — dit is cruciaal voor SDK's, bibliotheken en modulaire apps. In Jetpack Compose wordt lifecycle beheerd via LifecycleEventObserver en collectAsStateWithLifecycle, die gegevensverzameling automatisch pauzeert in de achtergrondmodus. Android 14 (API 34) voegde melding over foreground service lifecycle toe via Service.onTimeout — de service moet binnen 6 uur worden voltooid, anders stopt het systeem deze geforceerd.
| iOS | Android | Beschrijving |
|---|---|---|
| Not Running | — | App is niet gestart |
| didFinishLaunching | Application.onCreate | Eerste initialisatie bij starten |
| Active | onResume | App zichtbaar en ontvangt invoer |
| Inactive | onPause | Tijdelijk focusverlies (oproep, gordijn) |
| Background | onStop | App verborgen, code kan worden uitgevoerd |
| Suspended | — | Code wordt niet uitgevoerd, geheugen gereserveerd |
| Will Terminate | onDestroy | App wordt beëindigd |
Belangrijkste verschil: iOS dwingt de app 5-10 seconden na achtergrondgang naar Suspended (code wordt niet uitgevoerd). Android staat achtergrondwerk (services, WorkManager) langer toe, maar met Doze Mode-beperkingen (Android 6+) en achtergrondbeperkingen (Android 12+). ProcessLifecycleOwner in Android — analoog aan UIApplicationDidEnterBackgroundNotification in iOS met het verschil dat het bij elke achtergrondgang activeert, niet alleen na focusverlies.
Basisimplementatie van AppDelegate met verwerking van alle levenscyclustoestanden. Gegevensopslag bij achtergrondgang en UI-update bij terugkeer.
import UIKit
@main
class AppDelegate: UIResponder, UIApplicationDelegate {
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [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 — centraal punt van lifecycle. applicationDidEnterBackground — kritieke methode: iOS geeft ~5 seconden voor gegevensopslag. applicationDidBecomeActive — werk UI bij, herstart animaties. Voor SceneDelegate (iOS 13+) wordt lifecycle-logica verdeeld over scènes: sceneDidBecomeActive / sceneDidEnterBackground beheren afzonderlijke vensters.
SceneDelegate voor multi-venster iPad-apps. Elke scène heeft een eigen lifecycle, onafhankelijk van andere vensters.
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(_: UIScene) { PlayerManager.shared.resume() }
func sceneDidEnterBackground(_: UIScene) { PlayerManager.shared.pause(); CoreDataManager.shared.saveContext() }
func sceneDidDisconnect(_: UIScene) { PlayerManager.shared.cleanup() }
}SceneDelegate beheert de lifecycle van een afzonderlijke scène. sceneDidBecomeActive / sceneDidEnterBackground — equivalent van AppDelegate-methoden voor een specifiek venster. sceneDidDisconnect wordt aangeroepen bij sluiten van de scène (gebruiker sloot venster op iPad). Voor compatibiliteit met iOS 12 en ouder moet AppDelegate de SceneDelegate-logica dupliceren. In iOS 17+ kunt u @Observable gebruiken voor automatisch pauzeren/hervatten van taken op basis van scenePhase.
ProcessLifecycleOwner volgt wanneer de app in foreground/background is op procesniveau. Dit is de optimale manier voor globaal lifecycle-beheer.
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 — de enige correcte manier om achtergrondgang op app-niveau te volgen. ON_START wordt geactiveerd wanneer de app zichtbaar wordt (foreground), ON_STOP — wanneer volledig verborgen (background). In tegenstelling tot Activity lifecycle is ProcessLifecycleOwner niet gekoppeld aan een specifiek scherm. Gebruik voor Jetpack Compose LifecycleResumeEffect of collectAsStateWithLifecycle in plaats van handmatige observatie.
ViewModel + Lifecycle — de juiste Android-architectuur voor werken met lifecycle. ViewModel wordt automatisch opgeschoond bij onDestroy, voorkomt geheugenlekken.
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 — resources vrijgeven") }
}
// In 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 — animaties pauzeren") }
override fun onDestroy() { super.onDestroy(); Logger.d("Activity destroyed — opschonen") }
}ViewModel overleeft schermrotatie en wordt alleen vernietigd bij finish() Activity. onCleared() — plaats voor het vrijgeven van resources, uitschrijven van streams. LiveData pauzeert automatisch observatie bij onPause en hervat bij onResume — bescherming tegen lekken en crashes tijdens achtergrondwerk. Gebruik in Compose collectAsStateWithLifecycle() voor hetzelfde doel.
Veelgestelde vragen
Bij minimaliseren gaat de app van active naar inactive (kort), vervolgens naar background. Na enkele seconden kan het systeem deze naar suspended brengen — code wordt niet uitgevoerd, geheugen is gereserveerd. Bij geheugentekort wordt de suspended-app beëindigd (willTerminate wordt niet aangeroepen). Sla gegevens op in applicationDidEnterBackground — dit is het laatste gegarandeerde punt voor opslag.
Minimaal verplicht: applicationDidEnterBackground — gebruikersgegevens opslaan; applicationWillEnterForeground — UI bijwerken; in Android onPause — animaties/sensoren pauzeren. ProcessLifecycleOwner vereenvoudigt verwerking: onResume — onPause voor foreground, onStart — onStop voor zichtbaarheid. Verwerk overige toestanden indien nodig — niet alle toestanden zijn kritiek voor elke app.
AppDelegate — globale afgevaardigde van de hele app (starten, achtergrondgang). SceneDelegate (iOS 13+) beheert de lifecycle van een afzonderlijk venster (scene) — in multi-venster iPad-apps heeft elke scene zijn eigen lifecycle. Voor iOS 12 en ouder wordt de hele lifecycle verwerkt via AppDelegate. Vanaf iPadOS 16+ is SceneDelegate verplicht voor Stage Manager.
ProcessLifecycleOwner — component uit AndroidX Lifecycle die de lifecycle van de hele app (proces) volgt, niet van een afzonderlijke Activity. Biedt twee hoofdgebeurtenissen: ON_RESUME (app in foreground) en ON_STOP (app in background). Gebruikt voor initialisatie/opschoning van SDK's, analytics, netwerkmonitors — alles dat moet reageren op achtergrondgang van de app, ongeacht het huidige scherm.
In Jetpack Compose gebruikt u LifecycleEventObserver via LocalLifecycleOwner.current.lifecycle of de functie collectAsStateWithLifecycle(). Voor Compose-schermen past u LifecycleResumeEffect toe — analoog aan DisposableEffect dat start bij onResume en opschoont bij onPause. lifecycleScope.launchWhenResumed — coroutine automatisch gepauzeerd op de achtergrond.
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