Wichtige Erkenntnisse
App Lifecycle ist eine endliche Zustandsmaschine, die alle möglichen Zustände einer mobilen Anwendung und die Übergänge zwischen ihnen beschreibt. Jeder Zustand bestimmt, ob die App Code ausführen, die Benutzeroberfläche anzeigen und Ressourcen verbrauchen kann. iOS und Android haben ähnliche, aber nicht identische Modelle — die Unterschiede ergeben sich aus der OS-Architektur: iOS verwendet strenge Speicherkontrolle (Suspended-Zustand), während Android flexible Prozessverwaltung über onSaveInstanceState verwendet.
Unter iOS ist der Lebenszyklus eng an Vordergrund/Hintergrund gebunden: Die App ist entweder aktiv oder angehalten. Unter Android ist der Lebenszyklus granulärer — eine Activity/ein Fenster durchläuft 6+ Zustände, und der Prozess selbst hat einen zusätzlichen Lebenszyklus durch ProcessLifecycleOwner. Moderne Anwendungen (ab 2024) verwenden zunehmend lebenszyklusbasierte Architekturmuster: SwiftUI Lifecycle (iOS 16+) über die .scenePhase-Umgebung, Compose Lifecycle über LifecycleEventObserver. Diese Muster verarbeiten Kontextwechsel automatisch und verhindern Speicherlecks. Laut Google reduziert die korrekte Lebenszyklusbehandlung unter Android den Speicherverbrauch um 30–40 % bei Hintergrundarbeit.
Unter iOS wird der App-Lebenszyklus über die Klasse UIApplicationDelegate (AppDelegate) verwaltet. Die wichtigsten Methoden: application(_:didFinishLaunchingWithOptions:) — Initialisierung beim ersten Start; applicationDidBecomeActive — die App ist sichtbar und bereit zur Interaktion; applicationWillResignActive — Übergang in den inaktiven Zustand (eingehender Anruf, Schließen des Benachrichtigungs-Shades); applicationDidEnterBackground — die App ist ausgeblendet, ~5 Sekunden zum Speichern von Daten; applicationWillEnterForeground — Rückkehr aus dem Hintergrund; applicationWillTerminate — Beendigung (wird nur für ältere Apps ohne Suspended aufgerufen).
Ab iOS 13 führte Apple SceneDelegate (UISceneDelegate) ein, um Multi-Fenster-Anwendungen auf iPad und macOS Catalyst zu unterstützen. SceneDelegate verwaltet den Lebenszyklus jeder einzelnen Szene (Fenster): scene(_:willConnectTo:options:) — Szenenerstellung; sceneDidBecomeActive — Szene ist aktiv; sceneWillResignActive — Szene verliert den Fokus; sceneDidEnterBackground — Szene ist ausgeblendet. AppDelegate kümmert sich um globale Ereignisse (Daten laden, Push-Benachrichtigungen), während SceneDelegate den UI-Zustand jedes Fensters verwaltet. In SwiftUI wird der Lebenszyklus über den Umgebungswert @Environment(\.scenePhase): .active, .inactive, .background verwaltet — dies bietet eine einheitliche API für SwiftUI- und UIKit-Anwendungen.
Unter Android beginnt der Lebenszyklus mit der Klasse Application — einem Singleton, das vor jeder Activity erstellt wird. Die Methode Application.onCreate() ist der erste Einstiegspunkt, der für die globale Initialisierung (Analytics, DI, Crash Reporting) verwendet wird. Danach wird die Activity mit der Sequenz gestartet: onCreate() → onStart() → onResume(). Beim Minimieren: onPause() → onStop() → onSaveInstanceState(). Beim Zerstören: onDestroy(). Bei Rückkehr: onRestart() → onStart() → onResume().
ProcessLifecycleOwner (aus AndroidX Lifecycle 2.2+) verfolgt den Lebenszyklus des gesamten Prozesses, nicht einer einzelnen Activity. Es bietet zwei Zustände: ON_RESUME (App im Vordergrund) und ON_STOP (App ausgeblendet). ProcessLifecycleOwner löst das Problem „Wann ist die App in den Hintergrund gegangen“ auf Prozessebene — dies ist kritisch für SDKs, Bibliotheken und modulare Anwendungen. In Jetpack Compose wird der Lebenszyklus über LifecycleEventObserver und collectAsStateWithLifecycle verwaltet, das die Datensammlung im Hintergrundmodus automatisch aussetzt. Android 14 (API 34) fügte eine Benachrichtigung über den Lebenszyklus von Vordergrunddiensten über Service.onTimeout hinzu — der Dienst muss innerhalb von 6 Stunden abgeschlossen sein, andernfalls stoppt das System ihn zwangsweise.
| iOS | Android | Beschreibung |
|---|---|---|
| Not Running | — | App wurde nicht gestartet |
| didFinishLaunching | Application.onCreate | Erste Initialisierung beim Start |
| Active | onResume | App ist sichtbar und nimmt Eingaben entgegen |
| Inactive | onPause | Vorübergehender Fokusverlust (Anruf, Benachrichtigungs-Shade) |
| Background | onStop | App ist ausgeblendet, Code kann ausgeführt werden |
| Suspended | — | Code wird nicht ausgeführt, Speicher ist reserviert |
| Will Terminate | onDestroy | App wird beendet |
Der Hauptunterschied: iOS versetzt die App 5-10 Sekunden nach dem Eintritt in den Hintergrund zwangsweise in den Suspended-Zustand (Code wird nicht ausgeführt). Android erlaubt Hintergrundarbeit (Dienste, WorkManager) für einen längeren Zeitraum, jedoch mit Einschränkungen durch den Doze-Modus (Android 6+) und Hintergrundbeschränkungen (Android 12+). ProcessLifecycleOwner unter Android ist das Äquivalent von UIApplicationDidEnterBackgroundNotification unter iOS, mit dem Unterschied, dass es bei jedem Übergang in den Hintergrund ausgelöst wird, nicht nur nach Fokusverlust.
Basisimplementierung von AppDelegate, die alle Lebenszyklus-Zustände behandelt. Speichern von Daten beim Übergang in den Hintergrund und Aktualisieren der Benutzeroberfläche bei der Rückkehr.
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 ist der zentrale Lebenszyklus-Punkt. applicationDidEnterBackground ist eine kritische Methode: iOS gibt ~5 Sekunden zum Speichern. applicationDidBecomeActive — UI aktualisieren, Animationen neu starten. Für SceneDelegate (iOS 13+) wird die Lebenszyklus-Logik auf Szenen verteilt: sceneDidBecomeActive / sceneDidEnterBackground verwalten einzelne Fenster.
SceneDelegate für Multi-Fenster-iPad-Anwendungen. Jede Szene hat einen eigenen Lebenszyklus, unabhängig von anderen Fenstern.
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 verwaltet den Lebenszyklus einer einzelnen Szene. sceneDidBecomeActive / sceneDidEnterBackground sind die Entsprechungen der AppDelegate-Methoden für ein bestimmtes Fenster. sceneDidDisconnect wird beim Schließen einer Szene aufgerufen (der Benutzer hat ein Fenster auf iPad geschlossen). Für die Kompatibilität mit iOS 12 und älter muss AppDelegate die SceneDelegate-Logik duplizieren. Unter iOS 17+ können Sie @Observable verwenden, um Aufgaben basierend auf dem scenePhase automatisch anzuhalten/fortzusetzen.
ProcessLifecycleOwner verfolgt, wann sich die App auf Prozessebene im Vordergrund/Hintergrund befindet. Dies ist der optimale Ansatz für globales Lebenszyklus-Management.
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 ist die einzig korrekte Möglichkeit, den Übergang in den Hintergrund auf Anwendungsebene zu verfolgen. ON_START wird ausgelöst, wenn die App sichtbar wird (Vordergrund), ON_STOP — wenn sie vollständig ausgeblendet ist (Hintergrund). Im Gegensatz zum Activity-Lebenszyklus ist ProcessLifecycleOwner nicht an einen bestimmten Bildschirm gebunden. Verwenden Sie für Jetpack Compose LifecycleResumeEffect oder collectAsStateWithLifecycle anstelle manueller Beobachtung.
ViewModel + Lifecycle ist die korrekte Android-Architektur für das Lebenszyklus-Management. ViewModel wird bei onDestroy automatisch bereinigt und verhindert Speicherlecks.
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 — Ressourcen freigeben")
}
}
// 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 — Animationen anhalten")
}
override fun onDestroy() {
super.onDestroy()
Logger.d("Activity destroyed — Bereinigung")
}
}
ViewModel überlebt die Bildschirmdrehung und wird nur beim Beenden der Activity zerstört. onCleared() ist der Ort zum Freigeben von Ressourcen und Abbestellen von Streams. LiveData pausiert die Beobachtung bei onPause automatisch und setzt sie bei onResume fort — dies bietet Schutz vor Speicherlecks und Abstürzen während der Hintergrundarbeit. Verwenden Sie in Compose collectAsStateWithLifecycle() für denselben Zweck.
Häufig gestellte Fragen
Beim Minimieren wechselt die App von aktiv zu inaktiv (kurz), dann in den Hintergrund. Nach einigen Sekunden kann das System sie in den Suspended-Zustand versetzen — Code wird nicht ausgeführt, Speicher ist reserviert. Bei Speichermangel beendet das System die angehaltene App (willTerminate wird nicht aufgerufen). Speichern Sie Ihre Daten in applicationDidEnterBackground — dies ist der letzte garantierte Punkt zum Speichern.
Mindestens erforderlich: applicationDidEnterBackground — Benutzerdaten speichern; applicationWillEnterForeground — UI aktualisieren; unter Android onPause — Animationen/Sensoren anhalten. ProcessLifecycleOwner vereinfacht die Verarbeitung: onResume — onPause für Vordergrund, onStart — onStop für Sichtbarkeit. Behandeln Sie andere Zustände nach Bedarf — nicht alle Zustände sind für jede Anwendung kritisch.
AppDelegate ist der globale Delegat der gesamten Anwendung (Start, Hintergrundübergang). SceneDelegate (iOS 13+) verwaltet den Lebenszyklus eines einzelnen Fensters (Szene) — in Multi-Fenster-iPad-Anwendungen hat jede Szene ihren eigenen Lebenszyklus. Für iOS 12 und älter wird der gesamte Lebenszyklus über AppDelegate abgewickelt. Mit iPadOS 16+ ist SceneDelegate für Stage Manager erforderlich.
ProcessLifecycleOwner ist eine Komponente aus AndroidX Lifecycle, die den Lebenszyklus der gesamten Anwendung (Prozess) verfolgt, nicht einer einzelnen Activity. Es bietet zwei Hauptereignisse: ON_RESUME (App im Vordergrund) und ON_STOP (App im Hintergrund). Es wird zur Initialisierung/Bereinigung von SDKs, Analysen, Netzwerkmonitoren verwendet — alles, was auf den Übergang der App in den Hintergrund reagieren soll, unabhängig vom aktuellen Bildschirm.
Verwenden Sie in Jetpack Compose LifecycleEventObserver über LocalLifecycleOwner.current.lifecycle oder die Funktion collectAsStateWithLifecycle(). Verwenden Sie für Compose-Bildschirme LifecycleResumeEffect — ähnlich wie DisposableEffect, das bei onResume ausgeführt und bei onPause bereinigt wird. lifecycleScope.launchWhenResumed — eine Coroutine, die im Hintergrund automatisch ausgesetzt wird.
Zusammenfassung
Wir entwickeln eine mobile Applikation schlüsselfertig
IT Sectr entwickelt seit 2017 iOS- und Android-Apps für Startups und Unternehmen. Wir beraten Sie und schlagen die beste Lösung vor.
Lesen Sie auch