一、用户交互触发:Launcher 到 AMS 的跨进程通信
1. Launcher 处理点击事件(应用层)
当用户点击手机桌面上的应用图标时,Launcher(桌面应用)首先捕获点击事件。每个图标对应一个启动 Intent (通常是ACTION_MAIN
+ CATEGORY_LAUNCHER
),Launcher 通过这个 Intent 告诉系统 "我要启动某个应用的主 Activity"。
java
// Launcher.java
public void onClick(View v) {
Intent intent = getIntentForShortcut(v); // 获取启动 Intent
startActivitySafely(intent, null);
}
private void startActivitySafely(Intent intent, Bundle options) {
mContext.startActivity(intent, options); // 调用 Context.startActivity()
}
2. Context.startActivity () 转向 AMS(Framework 层)
接下来,Launcher 调用startActivity()
,这个看似简单的方法会逐层向上传递,最终到达 Android 系统的 "管家"------ActivityManagerService(AMS)。AMS 是运行在系统进程中的核心服务,负责管理所有应用的 Activity 和进程。
java
// ContextImpl.java
public void startActivity(Intent intent, Bundle options) {
// 包装 Intent 为显式 Intent(确保目标组件明确)
intent = Intent.parseIntentOrNull(this, intent, 0);
mMainThread.getInstrumentation().execStartActivity(
this, mMainThread.getApplicationThread(), null,
(Activity) null, intent, -1, options);
}
// Instrumentation.java
public ActivityResult execStartActivity(
Context who, IBinder contextThread, IBinder token,
Activity target, Intent intent, int requestCode, Bundle options) {
// 通过 AMS 的代理对象发起启动请求
return ActivityTaskManager.getService().startActivity(
whoThread, who.getBasePackageName(), intent,
... // 省略参数
);
}
二、AMS 核心逻辑:任务调度与进程管理
1. AMS.startActivity () 入口(SystemServer 进程)
AMS 作为系统服务,运行在 SystemServer
进程中,通过 Binder 接收启动请求后,首先进行权限校验和组件解析:
java
// ActivityTaskManagerService.java(继承 AMS)
@Override
public int startActivity(IApplicationThread caller, ...) {
// 检查调用者权限(如声明的 launcher 权限)
enforceNotIsolatedCaller("startActivity");
// 解析 Intent 对应的 Activity 组件(可能涉及隐式 Intent 匹配)
ActivityInfo aInfo = resolveActivity(intent, ...);
// 启动核心流程:创建任务栈(Task)或复用已有任务
return startActivityAsUser(intent, aInfo, ..., UserHandle.getCallingUserId());
}
private int startActivityAsUser(Intent intent, ActivityInfo aInfo, ...) {
// 构建启动参数包 ActivityStartData
ActivityStartData startData = new ActivityStartData();
// 核心调度逻辑:处理 Activity 启动的状态机
return mActivityStarter.startActivityMayWait(
caller, -1, startData, ...
);
}
2. 任务栈与 Activity 状态机(ActivityStackSupervisor)
AMS 通过 ActivityStackSupervisor
管理任务栈(TaskStack),决定是否新建任务或复用现有任务。若目标 Activity 所在进程未启动,触发 进程创建流程:
java
// ActivityStarter.java
private int startActivityMayWait(...) {
// 检查目标进程是否存在
ProcessRecord targetProc = mService.getProcessRecordLocked(targetProcessName, ...);
if (targetProc == null || targetProc.thread == null) {
// 进程未启动,调用 Zygote 孵化新进程
targetProc = startProcessLocked(
targetProcessName, activityInfo.applicationInfo, ...
);
} else {
// 进程已存在,直接通知其启动 Activity
scheduleLaunchActivityLocked(r, ...);
}
}
1. 组件合法性校验
AMS 首先检查启动 Intent 对应的 Activity 是否存在(比如是否在 AndroidManifest.xml 中声明),以及调用者是否有权限启动(比如普通应用不能直接启动系统级 Activity)。如果一切合法,进入下一步。
2. 任务栈管理
每个应用的 Activity 运行在 ** 任务栈(Task)** 中。AMS 会判断目标 Activity 应该在哪个任务栈中启动:
- 如果是冷启动(应用进程未运行),创建新的任务栈;
- 如果是热启动(应用进程已在后台运行),则将任务栈切换到前台,复用已有进程。
3. 进程是否存在?
- 热启动:若目标进程已存在(比如应用之前被后台保留),AMS 直接通知该进程启动 Activity。
- 冷启动 :若进程不存在,AMS 会唤醒 Android 的 "进程孵化器"------Zygote。
三、Zygote 孵化应用进程:从 SystemServer 到应用进程
1. Zygote 进程的作用(.native 层)
Zygote 是 Android 进程的 "孵化器",预加载了 Java 运行时环境和系统资源(如 Framework 类),通过 fork()
快速创建应用进程,避免重复初始化开销。
AMS 通过 ZygoteProcess
类与 Zygote 通信:
java
// ZygoteProcess.java
public Process.ProcessStartResult startProcess(...) {
// 构建启动参数(类名通常为 "android.app.ActivityThread")
String args = "--activity-thread --nice-name=" + processName;
// 通过 socket 向 Zygote 发送启动请求
return zygoteSendArgsAndGetResult(openZygoteSocket(), args);
}
2. 应用进程初始化(ActivityThread.main ())
Zygote fork 出的新进程会执行 ActivityThread.main()
,这是应用进程的入口:
java
// ActivityThread.java
public static void main(String[] args) {
// 初始化 Looper(UI 线程消息循环)
Looper.prepareMainLooper();
// 创建 ApplicationThread(AMS 通信的 Binder 实现)
ActivityThread thread = new ActivityThread();
thread.attach(false, ...); // 绑定到 AMS
// 启动消息循环,处理 H handler 的消息
Looper.loop();
}
private void attach(boolean system, ...) {
// 通过 Binder 向 AMS 注册应用进程
final IActivityManager am = ActivityManager.getService();
am.attachApplication(mAppThread); // mAppThread 是 ApplicationThread 实例
}
Zygote 是 Android 系统中一个特殊的进程,它在系统启动时就已创建,并预加载了 Java 运行时环境(如类加载器、JIT 编译器)和系统资源(如 Framework 核心类、字体、颜色值)。
当 AMS 需要创建新的应用进程时,会向 Zygote 发送请求。Zygote 通过 **fork ()** 机制复制自身,生成新的应用进程。由于 fork 会共享内存数据,新进程无需重新加载基础资源,大大加快了启动速度(比直接启动一个空进程快 50% 以上)。
新进程的入口是ActivityThread.main()
,这里会初始化应用的主线程(UI 线程)和消息循环(Looper),并通过 Binder 机制向 AMS 注册自己,建立通信桥梁。
四、应用进程启动 Activity:从创建到渲染
1. AMS 通知应用启动 Activity(跨进程回调)
AMS 通过 ApplicationThread
(应用进程的 Binder 服务)回调 scheduleLaunchActivity
,触发 Activity 创建:
java
// ApplicationThread.java(ActivityThread 内部类)
@Override
public final void scheduleLaunchActivity(IBinder token, ...) {
// 发送消息到 UI 线程处理
sendMessage(H.LAUNCH_ACTIVITY, r);
}
// ActivityThread.H handler(处理消息)
private void handleLaunchActivity(ActivityClientRecord r, ...) {
// 创建 Activity 实例
Activity activity = performLaunchActivity(r, r.overrideConfig);
if (activity != null) {
// 调度 Activity 的生命周期
handleResumeActivity(r.token, ..., true, ...);
}
}
2. 反射创建 Activity 实例(Instrumentation 调用)
performLaunchActivity
通过反射创建 Activity,并调用 Application
和 Activity
的生命周期方法:
java
// ActivityThread.java
private Activity performLaunchActivity(ActivityClientRecord r, Configuration config) {
// 加载 Application 类
Application app = r.packageInfo.makeApplication(false, mInstrumentation);
// 反射创建 Activity(关键源码)
java.lang.ClassLoader cl = appContext.getClassLoader();
Activity activity = mInstrumentation.newActivity(
cl, component.getClassName(), r.intent
);
// 调用 Activity.onCreate()
mInstrumentation.callActivityOnCreate(activity, r.state);
return activity;
}
3. 界面渲染准备:WindowManager 添加窗口
Activity 的 onResume
触发窗口添加,通过 WindowManager
将 DecorView
添加到屏幕:
java
// Activity.java
public void onResume() {
super.onResume();
// 窗口可见,通知 AMS 状态变更
mWindow.makeVisible();
}
// PhoneWindow.java
void makeVisible() {
if (!mWindowAdded) {
// 通过 WindowManager 添加窗口(核心方法)
mWindowManager.addView(mDecor, mWindowAttributes);
mWindowAdded = true;
}
}
1. 创建 Application:全局初始化
应用进程启动后,首先创建Application 实例 (即你在 Manifest 中声明的 Application 类,若未声明则使用系统默认)。这里会调用Application.onCreate()
,进行全局初始化(如数据库连接、第三方 SDK 注册)。
注意:Application 的生命周期早于所有 Activity,且整个应用中只有一个实例。
2. 反射创建 Activity 实例
接下来,AMS 通过 Binder 通知应用进程启动目标 Activity。进程通过反射机制 创建 Activity 实例(例如你的MainActivity
),并按顺序调用生命周期方法:
Activity.onCreate()
:初始化界面组件(如setContentView
);Activity.onStart()
:Activity 可见但未出现在前台;Activity.onResume()
:Activity 获取焦点,界面开始渲染。
3. 窗口系统介入:从 Activity 到屏幕显示
每个 Activity 都关联一个Window (通常是PhoneWindow
),窗口中包含一个DecorView
(界面的根容器,如标题栏、内容区)。当 Activity 进入onResume
状态,系统通过WindowManager 将DecorView
添加到屏幕:
- 计算界面布局(Measure、Layout 阶段),确定每个控件的位置和大小;
- 调用
onDraw
方法绘制内容(如文字、图片、自定义图形),最终通过 Skia 引擎将绘制结果写入Surface
(图形缓冲区)。
五、SurfaceFlinger 合成最终界面(图形系统)
- Surface 创建 :
WindowManager.addView
会为DecorView
创建Surface
,通过SurfaceControl
与SurfaceFlinger
(系统图形服务)交互。 - 渲染管道 :
View 的measure
/layout
/draw
流程在 UI 线程执行,最终通过 Skia 将绘制指令写入Surface
,由SurfaceFlinger
合成到屏幕缓冲区。 - VSYNC 同步 :
Choreographer 监听屏幕垂直同步信号(60Hz),确保每帧在 16ms 内完成渲染,避免卡顿。
六、冷启动 vs 热启动:核心差异对比
阶段 | 冷启动(进程未存在) | 热启动(进程已存在) |
---|---|---|
进程创建 | 触发 Zygote fork,初始化 Application 和 Context | 复用已有进程,直接唤醒 Activity |
AMS 调度 | 新建 ProcessRecord,绑定 ApplicationThread | 查找现有 ProcessRecord,复用任务栈 |
生命周期调用 | onCreate () → onStart () → onResume () 全流程 | 仅调用 onResume ()(若 Activity 已存在于栈顶) |
耗时关键因素 | 类加载、资源初始化、布局渲染 | 任务栈状态恢复、界面重绘 |
七、面试官高频问题回答示例
问题 1:"应用启动流程中,AMS 如何与应用进程通信?"
回答:AMS 是系统的 "Activity 管家",主要负责:
- 合法性校验:检查启动 Intent 对应的组件是否存在、是否有权限启动;
- 任务栈管理:决定 Activity 在哪个任务栈中运行,处理前后台切换;
- 进程调度 :若应用进程未启动,触发 Zygote 创建新进程;若已启动,通知进程唤醒 Activity。
它通过 Binder 跨进程通信,协调 Launcher、应用进程、系统图形服务等模块的协作。
问题 2:"Zygote 对启动性能的优化作用是什么?"
回答:Zygote 预加载了以下内容:
- Java 运行时环境(ClassLoaders、JIT 编译缓存);
- Framework 核心类(如 Activity、View);
- 系统资源(字体、颜色值、布局参数)。
通过fork()
复制进程内存,避免重复初始化,使应用进程启动时间减少约 50%~70%(对比直接启动 Java 进程)。
问题 3:"冷启动时,Application 和 Activity 的创建顺序是怎样的?"
回答 :
严格顺序:
ActivityThread.performLaunchActivity
先创建Application
(调用Application.onCreate
);- 再通过反射创建
Activity
实例; - 最后调用
Activity.onCreate
。
注意:Application
的生命周期早于所有Activity
,且全局唯一。
问题 4:"为什么冷启动时会看到短暂白屏?"
回答 :
这是因为 Activity 的界面渲染需要时间。在onCreate()
中调用setContentView
后,系统需要经历 Measure(测量)、Layout(布局)、Draw(绘制)三个阶段,才能将界面显示到屏幕。
在界面渲染完成前,系统会显示 Activity 的主题背景(默认是白色),因此会出现短暂白屏。优化方法包括:
- 减少
onCreate()
中的耗时操作; - 使用
android:windowBackground
设置过渡动画或透明背景,提升用户体验。
八、总结:启动流程的核心脉络
用户点击图标 → Launcher 解析 Intent → AMS 跨进程调度 → Zygote fork 应用进程 →
ActivityThread 初始化 → 反射创建 Application/Activity → 调用生命周期方法 →
WindowManager 添加窗口 → SurfaceFlinger 合成界面
感谢观看!!!