Activity 是 Android 四大组件中最直观、最常接触的组件,也是应用架构的核心载体。每一个界面都对应一个 Activity 实例,其背后涉及 ActivityThread 的消息驱动、Instrumentation 的测试/监控层、AMS/ATMS 的远程调度以及 Window 的创建与管理。本文从源码出发,深入剖析 Activity 的生命周期状态机、Configuration 变化处理、launchMode 对 Task 的影响以及跨进程回调机制。
一、Activity 的进程归属:ActivityThread 与主线程
1.1 ActivityThread.main——应用进程的起点
每个 Android 应用进程本质上是由 Zygote fork 出来的 Java 虚拟机进程。进程的 Java 入口是 ActivityThread.main:
// frameworks/base/core/java/android/app/ActivityThread.java |
这里的核心要点:
Looper.prepareMainLooper()在主线程创建了一个 Looper 和 MessageQueue;Looper.loop()进入死循环,不断消费 MessageQueue 中的消息;- 所有 Activity 的生命周期回调(onCreate、onStart、onResume 等)都是通过主线程的 Handler(mH)分发执行的。
1.2 mH——ActivityThread 的内部 Handler
// frameworks/base/core/java/android/app/ActivityThread.java |
二、Activity 生命周期状态机
2.1 生命周期状态定义
在 AOSP 中,Activity 的生命周期被定义为一组明确的回调方法,但在 ATMS 内部,使用 ActivityRecord.State 枚举管理状态迁移:
// frameworks/base/services/core/java/com/android/server/wm/ActivityRecord.java |
2.2 生命周期状态迁移图
┌─────────────┐ |
2.3 Instrumentation——生命周期调用的中介层
Instrumentation 是 Activity 生命周期回调的中间层。所有 AMS/ATMS 发起的生命周期调用都经过 Instrumentation:
// frameworks/base/core/java/android/app/Instrumentation.java |
Instrumentation 的存在使得 Android 测试框架(如 Espresso、Robolectric)可以拦截和监控所有生命周期回调。
2.4 handleLaunchActivity——Activity 启动的核心
// frameworks/base/core/java/android/app/ActivityThread.java |
三、Configuration 变化处理
3.1 两种处理模式
当设备配置发生变化(如屏幕旋转、语言切换、夜间模式切换等)时,Activity 有两种响应模式:
模式 1:重建 Activity(默认行为)
系统销毁 Activity 再重新创建。完整流程:onPause → onStop → onDestroy → onCreate → onStart → onResume。
模式 2:onConfigurationChanged 回调
当 Activity 在 AndroidManifest 中声明 android:configChanges 时,系统不销毁 Activity,而是直接回调 onConfigurationChanged。
3.2 AMS/ATMS 端的处理
// frameworks/base/services/core/java/com/android/server/wm/ActivityRecord.java |
配置变更类型定义在 android.content.res.Configuration 和 android.content.pm.ActivityInfo 中:
CONFIG_ORIENTATION = 0x0002CONFIG_SCREEN_SIZE = 0x0400CONFIG_LOCALE = 0x0004CONFIG_KEYBOARD = 0x0010CONFIG_UI_MODE = 0x0200
3.3 onSaveInstanceState 与恢复
在 Activity 因配置变化被销毁前,系统调用 onSaveInstanceState(Bundle outState) 保存状态:
// frameworks/base/core/java/android/app/Activity.java |
恢复时,onCreate(Bundle savedInstanceState) 或 onRestoreInstanceState(Bundle savedInstanceState) 接收 saved instance state。
四、launchMode 对 Task 管理的影响
4.1 四种 launchMode
launchMode 在 AndroidManifest 的 <activity> 标签中声明,或在 Intent 中通过 flags 覆盖。
standard(默认):每次启动都创建新实例,放入调用者所在的 Task。
singleTop:如果目标 Activity 已在栈顶,则复用,调用 onNewIntent();否则新建实例。
singleTask:系统中只能有一个实例。如果已存在但在不同 Task,则将该 Task 移到前台,并清除其上的所有 Activity(或调用 onNewIntent,取决于 FLAG_ACTIVITY_CLEAR_TOP)。
singleInstance:与 singleTask 类似,但该 Activity 独占一个 Task,此 Task 不允许其他 Activity 进入。
4.2 源码中的处理(ActivityStarter)
// frameworks/base/services/core/java/com/android/server/wm/ActivityStarter.java |
4.3 Intent Flags 与 launchMode 的关系
Intent flags 可以覆盖 launchMode 行为:
FLAG_ACTIVITY_NEW_TASK:效果等同于 singleTaskFLAG_ACTIVITY_CLEAR_TOP:清除目标 Activity 之上的所有 ActivityFLAG_ACTIVITY_SINGLE_TOP:效果等同于 singleTopFLAG_ACTIVITY_CLEAR_TASK:启动前清除整个 Task
这些 flag 在 ActivityStarter.startActivityUnchecked() 中被综合处理。
五、ActivityClientRecord 与跨进程回调
5.1 ActivityClientRecord 的数据结构
App 进程中的每个 Activity 都对应一个 ActivityClientRecord,它包含 Activity 实例及其必要的上下文信息:
// frameworks/base/core/java/android/app/ActivityThread.java |
5.2 ApplicationThread——跨进程 Binder 回调
ApplicationThread 是 ActivityThread 的内部类,继承自 IApplicationThread.Stub,是 system_server 向 App 进程发送生命周期指令的 Binder 接口:
// frameworks/base/core/java/android/app/ActivityThread.java |
Android 10 引入 ClientTransaction 和 ClientLifecycleManager 统一了生命周期事务的编排:
// frameworks/base/services/core/java/com/android/server/wm/ClientLifecycleManager.java |
5.3 ClientTransaction 中的生命周期回调链
一个 ClientTransaction 包含多个 ClientTransactionItem(生命周期回调项),例如:
// 启动 Activity 的典型 transaction |
六、核心面试题
Q1:Activity 的 onNewIntent 在什么场景下被调用?其调用时机是怎样的?
onNewIntent 在 Activity 处于 singleTop(栈顶复用)、singleTask 或 singleInstance 模式时被调用。调用时机通常是:onPause → onNewIntent → onResume(如果 Activity 已经在前台)。如果是后台 Activity 被新 Intent 唤起,则生命周期顺序是:onNewIntent → onRestart → onStart → onResume。在 onNewIntent 中应调用 setIntent(intent) 更新内部存储的 Intent。
Q2:当一个 Activity 被部分遮挡(比如弹出 Dialog),它的生命周期如何变化?为什么?
弹出 Dialog 是同一个应用进程内的操作,不触发 AMS 级别的生命周期回调。Dialog 本质上是 Activity Window 之上的一个子窗口,Activity 仍然处于 RESUMED 状态。但如果 Dialog 是另一个 Activity 的(如启动一个半透明 Activity),则下层 Activity 执行 onPause(),停止交互但可见(PAUSED 状态)。从 Android 10 开始,半透明 Activity 已不被允许在其他 Activity 之上启动(resumedOnTop),系统会自动将其转为 STANDARD 行为。
Q3:Activity 的重建机制中,onRetainNonConfigurationInstance 和 ViewModel 的关系是什么?
onRetainNonConfigurationInstance() 是 Android 早期提供的跨配置变更保留对象机制。在 Android Architecture Components 推出后,ViewModel 成为推荐的方式,内部正是基于此机制实现的。ComponentActivity 的 getLastNonConfigurationInstance() 保存着 ViewModelStore,在 Activity 重建时恢复 ViewModel 实例。
AOSP 核心路径参考:
frameworks/base/core/java/android/app/ActivityThread.javaframeworks/base/core/java/android/app/Activity.javaframeworks/base/core/java/android/app/Instrumentation.javaframeworks/base/core/java/android/app/servertransaction/ClientTransaction.javaframeworks/base/services/core/java/com/android/server/wm/ActivityStarter.javaframeworks/base/services/core/java/com/android/server/wm/ActivityRecord.javaframeworks/base/services/core/java/com/android/server/wm/ClientLifecycleManager.java







