App Lifecycle: what it is, app states in iOS and Android

Author: IT Sectr Published: 2026-03-02 Reading time: 8 min
App Lifecycle is the sequence of states a mobile application goes through from launch to termination. Understanding the lifecycle is critical for resource management, data persistence, and ensuring stability. In iOS, the app passes through states: Not Running → Active → Inactive → Background → Suspended. In Android — through onCreate → onStart → onResume → onPause → onStop → onDestroy + onRestart. Each state gives the developer a window to save state, free resources, or prepare for coming back. According to Apple Documentation, ignoring lifecycle events is the cause of 40 % of crashes when minimizing an app. At IT Sectr, we have implemented ProcessLifecycleOwner in Android and the AppDelegate pattern in iOS as mandatory standards for all projects — this reduced background-related bugs by 60 %.

Key Takeaways

  • App Lifecycle — a set of app states from launch to termination, each with specific developer actions.
  • AppDelegate — the central iOS class for lifecycle handling: didFinishLaunching, didEnterBackground, willEnterForeground.
  • SceneDelegate — a delegate for individual scenes (iOS 13+), managing the lifecycle of each window in multi-window applications.
  • ProcessLifecycleOwner — an Android component from AndroidX Lifecycle that tracks the lifecycle of the entire process.
  • Application.onCreate — the first entry point of an Android application, called before any Activity.

What is App Lifecycle?

App Lifecycle is a finite state machine that describes all possible states of a mobile application and the transitions between them. Each state determines whether the app can execute code, display UI, and consume resources. iOS and Android have similar but not identical models — the differences stem from OS architecture: iOS uses strict memory control (suspended state), while Android uses flexible process management through onSaveInstanceState.

In iOS, the lifecycle is tightly bound to foreground/background: the app is either active or suspended. In Android, the lifecycle is more granular — an Activity/Window goes through 6+ states, and the process itself has an additional lifecycle through ProcessLifecycleOwner. Modern applications (since 2024) increasingly use architecture patterns based on lifecycle: SwiftUI Lifecycle (iOS 16+) via .scenePhase environment, Compose Lifecycle via LifecycleEventObserver. These patterns automatically handle context switching and prevent memory leaks. According to Google, proper lifecycle handling in Android reduces memory consumption by 30–40 % during background work.

iOS Lifecycle: AppDelegate and SceneDelegate

In iOS, the app lifecycle is managed through the UIApplicationDelegate class (AppDelegate). The main methods: application(_:didFinishLaunchingWithOptions:) — initialization on first launch; applicationDidBecomeActive — the app is visible and ready for interaction; applicationWillResignActive — transitioning to inactive state (incoming call, closing the notification shade); applicationDidEnterBackground — the app is hidden, ~5 seconds to save data; applicationWillEnterForeground — returning from background; applicationWillTerminate — termination (called only for older apps without suspended).

Starting with iOS 13, Apple introduced SceneDelegate (UISceneDelegate) to support multi-window applications on iPad and macOS Catalyst. SceneDelegate manages the lifecycle of each individual scene (window): scene(_:willConnectTo:options:) — scene creation; sceneDidBecomeActive — scene is active; sceneWillResignActive — scene loses focus; sceneDidEnterBackground — scene is hidden. AppDelegate handles global events (data loading, push notifications), while SceneDelegate handles the UI state of each window. In SwiftUI, lifecycle is handled through the environment value @Environment(\.scenePhase): .active, .inactive, .background — this provides a unified API for both SwiftUI and UIKit applications.

Android Lifecycle: Application and ProcessLifecycleOwner

In Android, the lifecycle starts with the Application class — a singleton created before any Activity. The Application.onCreate() method is the first entry point, used for global initialization (Analytics, DI, Crash Reporting). After that, the Activity launches with the sequence: onCreate() → onStart() → onResume(). When minimized: onPause() → onStop() → onSaveInstanceState(). When destroyed: onDestroy(). When returning: onRestart() → onStart() → onResume().

ProcessLifecycleOwner (from AndroidX Lifecycle 2.2+) tracks the lifecycle of the entire process, not an individual Activity. It provides two states: ON_RESUME (app in foreground) and ON_STOP (app is hidden). ProcessLifecycleOwner solves the problem of "when did the app go to background" at the process level — this is critical for SDKs, libraries, and modular applications. In Jetpack Compose, lifecycle is managed through LifecycleEventObserver and collectAsStateWithLifecycle, which automatically suspends data collection in background mode. Android 14 (API 34) added foreground service lifecycle notification via Service.onTimeout — the service must complete within 6 hours, otherwise the system forcibly stops it.

iOS and Android Lifecycle Comparison

iOS Android Description
Not Running App is not launched
didFinishLaunching Application.onCreate First initialization on launch
Active onResume App is visible and accepting input
Inactive onPause Temporary loss of focus (call, notification shade)
Background onStop App is hidden, code may be executing
Suspended Code is not executing, memory is reserved
Will Terminate onDestroy App is terminating

The main difference: iOS forcibly transitions the app to Suspended (code stops executing) 5-10 seconds after entering the background. Android allows background work (services, WorkManager) for a longer period, but with limitations from Doze Mode (Android 6+) and background restrictions (Android 12+). ProcessLifecycleOwner in Android is the equivalent of UIApplicationDidEnterBackgroundNotification in iOS, with the difference that it fires on any transition to background, not just after losing focus.

Code Examples

iOS: AppDelegate with Lifecycle Methods

A basic AppDelegate implementation handling all lifecycle states. Saving data when transitioning to background and updating UI when returning.

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 is the central lifecycle point. applicationDidEnterBackground is a critical method: iOS gives ~5 seconds for saving. applicationDidBecomeActive — update UI, restart animations. For SceneDelegate (iOS 13+), lifecycle logic is distributed across scenes: sceneDidBecomeActive / sceneDidEnterBackground manage individual windows.

iOS: SceneDelegate (iOS 13+)

SceneDelegate for multi-window iPad applications. Each scene has its own lifecycle, independent of other windows.

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 manages the lifecycle of an individual scene. sceneDidBecomeActive / sceneDidEnterBackground are the equivalents of AppDelegate methods for a specific window. sceneDidDisconnect is called when a scene closes (the user closed a window on iPad). For compatibility with iOS 12 and below, AppDelegate must duplicate SceneDelegate logic. In iOS 17+, you can use @Observable to automatically pause/resume tasks based on scenePhase.

Android: Application with ProcessLifecycleOwner

ProcessLifecycleOwner tracks when the app is in foreground/background at the process level. This is the optimal approach for global lifecycle management.

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 is the only correct way to track the transition to background at the application level. ON_START fires when the app becomes visible (foreground), ON_STOP — when completely hidden (background). Unlike Activity lifecycle, ProcessLifecycleOwner is not tied to a specific screen. For Jetpack Compose, use LifecycleResumeEffect or collectAsStateWithLifecycle instead of manual observation.

Android: Activity Lifecycle with ViewModel

ViewModel + Lifecycle is the correct Android architecture for lifecycle management. ViewModel is automatically cleared on onDestroy, preventing leaks.

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 — releasing resources")
    }
}

// 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 — pausing animations")
    }

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

ViewModel survives screen rotation and is only destroyed when the Activity finishes. onCleared() is the place to release resources and unsubscribe from streams. LiveData automatically pauses observation on onPause and resumes on onResume — this provides protection against leaks and crashes during background work. In Compose, use collectAsStateWithLifecycle() for the same purpose.

Frequently Asked Questions

What happens when a user minimizes an iOS app?

When minimized, the app transitions from active to inactive (briefly), then to background. After a few seconds, the system may move it to suspended — code stops executing, memory is reserved. When memory is low, the system terminates the suspended app (willTerminate is not called). Save your data in applicationDidEnterBackground — this is the last guaranteed point for saving.

Do I need to handle all App Lifecycle states?

Minimum required: applicationDidEnterBackground — save user data; applicationWillEnterForeground — update UI; in Android onPause — pause animations/sensors. ProcessLifecycleOwner simplifies handling: onResume — onPause for foreground, onStart — onStop for visibility. Handle other states as needed — not all states are critical for every application.

How is SceneDelegate different from AppDelegate?

AppDelegate is the global delegate of the entire application (launch, background transition). SceneDelegate (iOS 13+) manages the lifecycle of an individual window (scene) — in multi-window iPad applications, each scene has its own lifecycle. For iOS 12 and below, all lifecycle is handled through AppDelegate. With iPadOS 16+, SceneDelegate is required for Stage Manager.

What is ProcessLifecycleOwner in Android?

ProcessLifecycleOwner is a component from AndroidX Lifecycle that tracks the lifecycle of the entire application (process), not an individual Activity. It provides two main events: ON_RESUME (app in foreground) and ON_STOP (app in background). It is used for initialization/cleanup of SDKs, analytics, network monitors — anything that should react to the app transitioning to background, regardless of the current screen.

How to handle lifecycle in Jetpack Compose?

In Jetpack Compose, use LifecycleEventObserver through LocalLifecycleOwner.current.lifecycle or the collectAsStateWithLifecycle() function. For Compose screens, use LifecycleResumeEffect — similar to DisposableEffect, which runs on onResume and cleans up on onPause. lifecycleScope.launchWhenResumed — a coroutine that automatically suspends in the background.

Summary

  • App Lifecycle is a finite state machine of app states that determines resource management, data persistence, and stability.
  • iOS AppDelegate (applicationDidEnterBackground) is the critical method for saving data when transitioning to background within 5 seconds.
  • iOS SceneDelegate (iOS 13+) manages the lifecycle of each scene separately — required for multi-window iPad applications.
  • Android ProcessLifecycleOwner is a global process lifecycle observer for SDK initialization/cleanup.
  • ViewModel in Android survives screen rotation and is cleared on Activity finish — prevents memory leaks.
  • SwiftUI @Environment(\.scenePhase) provides a unified API for lifecycle in SwiftUI (active, inactive, background).
  • Proper lifecycle handling reduces memory consumption by 30-40% and prevents 40% of crashes during background work.

We will develop a mobile application turnkey

IT Sectr creates iOS and Android applications for startups and businesses since 2017. We will advise you and propose the best solution.

Discuss the project

Read also