要点
App Lifecycle — 一个有限状态机,描述移动应用程序所有可能的状态及它们之间的转换。每个状态决定应用程序是否可以执行代码、显示UI和消耗资源。iOS和Android有相似但不相同的模型 — 差异源于操作系统架构:iOS使用严格的内存控制(suspended状态),Android — 通过onSaveInstanceState进行灵活的过程管理。
在iOS中,生命周期与前台/后台紧密相关:应用程序要么是活动的,要么是挂起的。在Android中,生命周期更加细粒度 — Activity/Window经历6+个状态,进程本身通过ProcessLifecycleOwner拥有额外的生命周期。现代应用程序(从2024年起)越来越多地使用基于生命周期的架构模式:SwiftUI Lifecycle(iOS 16+)通过.scenePhase环境,Compose Lifecycle通过LifecycleEventObserver。这些模式自动处理上下文切换并防止内存泄漏。根据Google的数据,在Android中正确处理生命周期可将后台工作时的内存消耗减少30–40%。
在iOS中,应用程序的生命周期通过UIApplicationDelegate(AppDelegate)类管理。主要方法:application(_:didFinishLaunchingWithOptions:) — 首次启动时初始化;applicationDidBecomeActive — 应用程序可见并准备好交互;applicationWillResignActive — 过渡到非活动状态(来电、关闭屏幕);applicationDidEnterBackground — 应用程序隐藏,有约5秒保存数据;applicationWillEnterForeground — 从后台返回;applicationWillTerminate — 结束(仅对没有suspended的旧应用程序调用)。
从iOS 13开始,Apple引入了SceneDelegate(UISceneDelegate)来支持iPad和macOS Catalyst上的多窗口应用程序。SceneDelegate管理每个单独场景(窗口)的生命周期:scene(_:willConnectTo:options:) — 创建场景;sceneDidBecomeActive — 场景活动;sceneWillResignActive — 场景失去焦点;sceneDidEnterBackground — 场景隐藏。AppDelegate负责全局事件(数据加载、推送通知),SceneDelegate — 负责每个窗口的UI状态。在SwiftUI中,生命周期通过@Environment(\.scenePhase)环境值管理:.active、.inactive、.background — 这为SwiftUI和UIKit应用程序提供了统一的API。
在Android中,生命周期从Application类开始 — 一个在任何Activity之前创建的单例。Application.onCreate()方法 — 第一个入口点,用于全局初始化(Analytics、DI、Crash Reporting)。之后Activity按顺序启动:onCreate() → onStart() → onResume()。最小化时:onPause() → onStop() → onSaveInstanceState()。销毁时:onDestroy()。返回时:onRestart() → onStart() → onResume()。
ProcessLifecycleOwner(来自AndroidX Lifecycle 2.2+)跟踪整个进程的生命周期,而不是单个Activity。提供两种状态:ON_RESUME(应用程序在前台)和ON_STOP(应用程序隐藏)。ProcessLifecycleOwner在进程级别解决了"应用程序何时进入后台"的问题 — 这对于SDK、库和模块化应用程序至关重要。在Jetpack Compose中,生命周期通过LifecycleEventObserver和collectAsStateWithLifecycle管理,后者在后台模式下自动暂停数据收集。Android 14(API 34)通过Service.onTimeout添加了前台服务生命周期通知 — 服务必须在6小时内完成,否则系统将强制停止它。
| iOS | Android | 描述 |
|---|---|---|
| Not Running | — | 应用程序未运行 |
| didFinishLaunching | Application.onCreate | 启动时首次初始化 |
| Active | onResume | 应用程序可见并接收输入 |
| Inactive | onPause | 暂时失去焦点(电话、屏幕关闭) |
| Background | onStop | 应用程序隐藏,代码可执行 |
| Suspended | — | 代码不执行,内存保留 |
| Will Terminate | onDestroy | 应用程序结束 |
主要区别:iOS在进入后台5-10秒后强制将应用程序置于Suspended状态(代码不执行)。Android允许更长时间的后台工作(服务、WorkManager),但受Doze Mode(Android 6+)和后台限制(Android 12+)的约束。Android中的ProcessLifecycleOwner — 相当于iOS中的UIApplicationDidEnterBackgroundNotification,区别在于它在每次进入后台时触发,而不仅仅是在失去焦点后。
AppDelegate的基本实现,处理所有生命周期状态。在进入后台时保存数据,在返回时更新UI。
import UIKit
@main
class AppDelegate: UIResponder, UIApplicationDelegate {
func application(_: UIApplication, didFinishLaunchingWithOptions lo: [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 — 生命周期的中心点。applicationDidEnterBackground — 关键方法:iOS提供约5秒保存数据。applicationDidBecomeActive — 更新UI,重新启动动画。对于SceneDelegate(iOS 13+),生命周期逻辑分布到场景:sceneDidBecomeActive / sceneDidEnterBackground管理单个窗口。
适用于iPad多窗口应用程序的SceneDelegate。每个场景都有自己的生命周期,独立于其他窗口。
import UIKit
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
var window: UIWindow?
func scene(_: UIScene, willConnectTo s: UISceneSession, options o: UIScene.ConnectionOptions) {
guard let ws = (_ as? UIWindowScene) else { return }
window = UIWindow(windowScene: ws)
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管理单个场景的生命周期。sceneDidBecomeActive / sceneDidEnterBackground — 相当于特定窗口的AppDelegate方法。sceneDidDisconnect在场景关闭时调用(用户在iPad上关闭了窗口)。为了保持与iOS 12及更早版本的兼容性,AppDelegate必须复制SceneDelegate的逻辑。在iOS 17+中,您可以使用@Observable根据scenePhase自动暂停/恢复任务。
ProcessLifecycleOwner在进程级别跟踪应用程序何时在前台/后台。这是全局生命周期管理的最佳方式。
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 — 在应用程序级别跟踪后台转换的唯一正确方法。ON_START在应用程序变得可见(前台)时触发,ON_STOP — 在完全隐藏(后台)时触发。与Activity生命周期不同,ProcessLifecycleOwner不绑定到特定屏幕。对于Jetpack Compose,使用LifecycleResumeEffect或collectAsStateWithLifecycle代替手动观察。
ViewModel + Lifecycle — 用于处理生命周期的正确Android架构。ViewModel在onDestroy时自动清理,防止内存泄漏。
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 — 释放资源") }
}
// 在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 — 暂停动画") }
override fun onDestroy() { super.onDestroy(); Logger.d("Activity destroyed — 清理") }
}ViewModel能够承受屏幕旋转,仅在finish() Activity时被销毁。onCleared() — 释放资源和取消订阅数据流的地方。LiveData在onPause时自动暂停观察,在onResume时恢复 — 在后台工作期间提供防止泄漏和崩溃的保护。在Compose中使用collectAsStateWithLifecycle()实现相同目的。
常见问题
最小化时,应用程序从active进入inactive(短暂),然后进入background。几秒钟后,系统可能会将其置于suspended状态 — 代码不执行,内存保留。当内存不足时,suspended应用程序被终止(不会调用willTerminate)。在applicationDidEnterBackground中保存数据 — 这是最后一个有保证的保存点。
最低要求:applicationDidEnterBackground — 保存用户数据;applicationWillEnterForeground — 更新UI;在Android中onPause — 暂停动画/传感器。ProcessLifecycleOwner简化了处理:onResume — onPause用于前台,onStart — onStop用于可见性。其他状态根据需要处理 — 并非所有状态对每个应用程序都至关重要。
AppDelegate — 整个应用程序的全局委托(启动、进入后台)。SceneDelegate(iOS 13+)管理单个窗口(场景)的生命周期 — 在多窗口iPad应用程序中,每个场景都有自己的生命周期。对于iOS 12及更早版本,整个生命周期通过AppDelegate处理。从iPadOS 16+开始,SceneDelegate对于Stage Manager是必需的。
ProcessLifecycleOwner — 来自AndroidX Lifecycle的组件,跟踪整个应用程序(进程)的生命周期,而不是单个Activity。提供两个主要事件:ON_RESUME(应用程序在前台)和ON_STOP(应用程序在后台)。用于初始化/清理SDK、分析、网络监视器 — 所有应该对应用程序进入后台作出反应的内容,无论当前屏幕如何。
在Jetpack Compose中,通过LocalLifecycleOwner.current.lifecycle或collectAsStateWithLifecycle()函数使用LifecycleEventObserver。对于Compose屏幕,应用LifecycleResumeEffect — 相当于DisposableEffect,它在onResume时运行并在onPause时清理。lifecycleScope.launchWhenResumed — 在后台自动暂停的协程。
总结
我们将开发一款交钥匙移动应用程序
IT Sectr自2017年以来为初创企业和企业打造iOS和Android应用程序。我们将为您提供咨询并提出最佳解决方案。