Activity启动流程
启动一个 Activity,通常有两种情况,一种是在应用内部启动 Activity,另一种是 Launcher 启动。
一、应用内启动
当我们调用startActivity()时,这个请求会经过多个进程和系统服务,大致流程如下:
- 应用进程(调用者Activity所在进程)通过Binder调用到ActivityManagerService(AMS)。
- AMS处理启动请求,检查权限、目标Activity信息等。
- 如果目标Activity所在进程未启动,AMS会通知Zygote进程fork一个新进程。
- 新进程启动后,会创建ActivityThread,并调用main()方法,然后进入消息循环。
- 新进程通过Binder调用AMS的
attachApplication(),告诉AMS自己已经启动。 - AMS通过Binder调用新进程的
bindApplication(),传递应用信息,并创建目标Activity。 - 新进程开始Activity的生命周期调用,最终完成启动。
二、Launcher 启动
从桌面点击图标启动应用,实际上是从Launcher应用启动目标应用的主Activity。整个流程与普通的Activity启动类似,但Launcher本身也是一个应用,所以涉及到两个应用之间的启动过程。 整个流程可以分为以下几个阶段:
- Launcher进程向AMS发送启动目标应用主Activity的请求。
- AMS处理启动请求,如果目标应用进程不存在,则创建新进程。
- 目标应用进程启动,并创建主Activity,然后显示界面。
首先了解一下关键角色:
| 角色 | 所在进程 | 职责 |
|---|---|---|
| 调用者Activity | 应用进程 | 发动启动请求 |
| Instrumentation | 应用进程 | 监控应用程序与系统交互 |
| ActivityManagerService(AMS) | system_server进程 | 所有Activity的调度中心 |
| ApplicationThread | 应用进程 | AMS与应用进程通信的桥梁 |
| ActivityThread | 应用进程 | 应用主线程,管理Activity生命周期 |
| Zygote | zygote进程 | 孵化新进程 |
一次startActivity调用,本质上是应用进程请求系统进程(主要是ActivityTaskManagerService) 来调度和管理一个新的Activity。这个过程分为两段:
- 进程内调用链:在您的应用进程内传递,终点是发起一个跨进程调用(IPC)。
- 跨进程调用:通过Binder进入系统进程,由系统服务处理。
从startActivity()开始,
// 1. 从这里开始
public class MainActivity extends Activity {
public void startNewActivity() {
startActivity(new Intent(this, SecondActivity.class));
}
}
// 2. 进入Activity.java
public void startActivity(Intent intent) {
startActivity(intent, null); // Bundle options为null
}
public void startActivity(Intent intent, @Nullable Bundle options) {
// 关键调用:Instrumentation.execStartActivity()
if (options != null) {
mInstrumentation.execStartActivity(
this, mMainThread.getApplicationThread(),
mToken, this, intent, -1, options);
} else {
mInstrumentation.execStartActivity(
this, mMainThread.getApplicationThread(),
mToken, this, intent, -1);
}
}
// 3. Instrumentation.execStartActivity()
public ActivityResult execStartActivity(
Context who, // 调用者上下文,即当前Activity (this)
IBinder contextThread, // 核心!应用进程的Binder句柄
IBinder token, // 核心!当前Activity的标识令牌
Activity target, // 当前Activity (this)
Intent intent, // 要启动新Activity的Intent
int requestCode,
Bundle options
) {
// contextThread 实际是 ApplicationThread 的 Binder 代理
IApplicationThread whoThread = (IApplicationThread) contextThread;
try {
// 4. 关键调用:通过Binder跨进程调用AMS
int result = ActivityManager.getService()
.startActivity(whoThread, // ApplicationThread代理
who.getBasePackageName(), // 包名
intent,
intent.resolveTypeIfNeeded(who.getContentResolver()),
token, // 当前Activity的token
target != null ? target.mEmbeddedID : null,
requestCode, 0, null, options);
// 检查启动结果
checkStartActivityResult(result, intent);
} catch (RemoteException e) {
throw new RuntimeException("Failure from system", e);
}
return null;
}
以上是进程内调用链的最后几步。它的核心使命是:收集好所有必要参数,然后通过Binder IPC将启动请求“扔”给系统。
-
首先
Activity.startActivity()最终会调用重载方法,并准备一个关键的mInstrumentation对象。 -
每个应用进程有且仅有一个
Instrumentation实例。它由系统在启动进程时创建,并关联到主线程(ActivityThread)。它才是应用进程中真正“执行”Activity、Application生命周期方法(如onCreate,onStart)的组件。系统进程通过Binder调用通知ApplicationThread,ApplicationThread会转交给Instrumentation来实际调用。在当前startActivity的场景下,它负责将调用打包,并通过Binder转发给系统。 -
ActivityManager.getService()返回的是AMS的Binder代理对象。调用从这里离开应用进程,进入system_server进程,是进程内调用链的终点和跨进程调用的起点。
现在进入到system_server进程,ActivityTaskManagerService(ATMS) 开始工作
这里解释一下,在Android 10之前,AMS(ActivityManagerService)负责所有Activity管理。Android 10引入ATMS,将Activity和任务栈管理从AMS中分离出来,实现关注点分离。其职责包括Activity生命周期的管理,任务栈和返回栈管理,Activity启动模式处理,Activity转场动画管理,多窗口模式支持。
// 5. ActivityManagerService.startActivity()
public final int startActivity(IApplicationThread caller,
String callingPackage, Intent intent,
String resolvedType, IBinder resultTo,
String resultWho, int requestCode,
int startFlags, ProfilerInfo profilerInfo,
Bundle bOptions) {
return startActivityAsUser(caller, callingPackage, intent,
resolvedType, resultTo, resultWho,
requestCode, startFlags, profilerInfo,
bOptions, UserHandle.getCallingUserId());
}
// ATMS不直接处理启动逻辑,而是委托给专门的控制器
private int startActivityAsUser(...) {
// 关键:获取Activity启动控制器
return getActivityStartController().obtainStarter(intent, "startActivity")
.setCaller(caller)
.setCallingPackage(callingPackage)
.setIntent(intent)
// ... 设置所有参数
.execute();
}
int execute() {
try {
// 解析Intent,找到目标Activity
int res = startActivityMayWait(...);
return res;
} finally {
onExecutionComplete();
}
}
// 6. 经过多个调用,最终到ActivityStarter
// ActivityStarter是真正的启动引擎,它处理所有复杂的启动逻辑
class ActivityStarter {
int startActivityMayWait(...) {
// 7. 这里进行复杂的检查和处理:
// - 权限检查
// - Activity是否存在
// - 启动模式处理
// - 任务栈管理
// 8. 获取目标Activity信息
ActivityInfo aInfo = resolveActivity(intent, resolvedType, startFlags, profilerInfo);
// 9. 处理启动模式(重点!)
// 如果是singleTask,会查找现有任务栈
// 如果是singleInstance,会创建新任务栈
// 10. 检查目标进程是否存在
ProcessRecord app = mService.getProcessRecordLocked(
targetProcessName, info.applicationInfo.uid);
if (app != null && app.thread != null) {
// 进程已存在,直接启动Activity
realStartActivityLocked(r, app, andResume, checkConfig);
} else {
// 11. 需要创建新进程!
mService.startProcessLocked(targetProcessName,
info.applicationInfo,
knownToBeDead, false,
intent.getFlags());
}
}
}
ATMS在这里做了大量决策,特别是处理启动模式(Launch Mode),后续整理。
如果目标Activity的进程不存在,AMS会通过Zygote创建新进程。
是否需要创建新进程取决于目标Activity所在的应用程序进程是否已经存在。
| 场景 | 结果 |
|---|---|
| 启动同一个应用内的Activity | 复用现有进程,在同一个进程中创建新Activity |
| 启动其他应用,但该应用已在运行 | 复用目标应用的已有进程 |
| 多任务栈,但进程相同 | 创建新的任务栈,但复用进程 |
| 首次启动应用 | 应用从未启动过,或应用进程已被系统回收,创建新进程 |
| 应用配置了多进程 | 为独立进程创建新进程,常见后台播放器, Webview隔离进程等 |
// 12. ATMS请求Zygote创建进程
final ProcessRecord startProcessLocked(String processName,
ApplicationInfo info,
boolean knownToBeDead,
int intentFlags,
String hostingType) {
// 通过Socket通知Zygote fork新进程
Process.ProcessStartResult startResult = Process.start(
"android.app.ActivityThread", // 入口类,新进程的主类
app.processName, uid, uid, gids,
debugFlags, mountExternal,
app.info.targetSdkVersion,
app.info.seinfo,
app.info.abi,
app.info.dataDir,
null);
// 保存进程记录
app.setPid(startResult.pid);
app.thread = null; // 还未连接
}
新进程被创建后,来到该应用进程,执行入口ActivityThread.main()
// 13. 新进程的入口点
public static void main(String[] args) {
// 1. 准备主线程Looper
Looper.prepareMainLooper();
// 2. 创建ActivityThread实例
ActivityThread thread = new ActivityThread();
// 3. 关键:attach到AMS
thread.attach(false, startSeq);
// 4. 开始消息循环
Looper.loop();
}
// 14. attach到ATMS
private void attach(boolean system, long startSeq) {
// 获取ATMS的Binder代理
final IActivityManager mgr = ActivityManager.getService();
try {
// 告诉ATMS:我准备好了,这是我的ApplicationThread
mgr.attachApplication(mAppThread, startSeq);
} catch (RemoteException ex) {
throw ex.rethrowFromSystemServer();
}
}
每个应用进程都有一个ApplicationThread对象,它是AMS回调应用进程的"电话线",而后回到ATMS进程,处理新进程的attach。
// 15. AMS.attachApplication()
public final void attachApplication(IApplicationThread thread, long startSeq) {
synchronized (this) {
// 找到对应的进程记录
ProcessRecord app = getProcessRecordLocked(thread);
if (app != null) {
// 绑定进程
bindApplication(thread, ...);
// 16. 现在可以启动Activity了!
if (mStackSupervisor.attachApplicationLocked(app)) {
// 这里会找到等待启动的Activity
realStartActivityLocked(activity, app, true, true);
}
}
}
}
// 17. 真正启动Activity,之前不需要创建新进程的话直接来到这里
final boolean realStartActivityLocked(ActivityRecord r,
ProcessRecord app,
boolean andResume,
boolean checkConfig) {
// 通过Binder回调到应用进程
app.thread.scheduleLaunchActivity(
new Intent(r.intent), r.appToken,
System.identityHashCode(r), r.info,
mergedConfiguration, r.compat, r.launchedFromPackage,
task.voiceInteractor, app.repProcState, r.icicle,
r.persistentState, results, newIntents,
!andResume, mService.isNextTransitionForward(),
profilerInfo);
return true;
}
接下来到新进程,应用进程,来创建Activity实例
// 18. ApplicationThread.scheduleLaunchActivity()
// ApplicationThread是ActivityThread的内部类
private class ApplicationThread extends IApplicationThread.Stub {
public final void scheduleLaunchActivity(...) {
// 发送消息到主线程Handler
sendMessage(H.LAUNCH_ACTIVITY, r);
}
}
// 19. ActivityThread.H处理消息
class H extends Handler {
public void handleMessage(Message msg) {
switch (msg.what) {
case LAUNCH_ACTIVITY:
handleLaunchActivity(r, null, "LAUNCH_ACTIVITY");
break;
}
}
}
// 20. 创建Activity实例
private void handleLaunchActivity(ActivityClientRecord r,
Intent customIntent, String reason) {
// 1. 创建Activity实例(反射)
Activity activity = mInstrumentation.newActivity(
cl, component.getClassName(), r.intent);
// 2. 创建Application(如果不存在)
Application app = r.packageInfo.makeApplication(false, mInstrumentation);
// 3. 关联Context
activity.attach(appContext, this, getInstrumentation(), r.token,
r.ident, app, r.intent, r.activityInfo,
title, r.parent, r.embeddedID,
r.lastNonConfigurationInstances, config,
r.referrer, r.voiceInteractor, window);
// 4. 调用onCreate()
mInstrumentation.callActivityOnCreate(activity, r.state);
// 5. 调用onStart()和onResume()
if (!r.activity.mFinished) {
activity.performStart();
r.activity.mResumed = true;
}
}
简述:
"具体来说,当我们调用startActivity()时,首先通过Instrumentation跨进程调用AMS的startActivity方法。AMS会进行一系列检查,包括权限验证、Activity是否存在、启动模式处理等。如果目标进程不存在,AMS会通过Zygote fork新进程。新进程启动后执行ActivityThread.main(),并通过attachApplication()告诉AMS自己已就绪。AMS接着通过ApplicationThread这个Binder代理回调到应用进程,最终在主线程中通过反射创建Activity实例,并依次调用onCreate、onStart、onResume。整个过程涉及到至少两次Binder跨进程调用,以及复杂的任务栈管理逻辑。"
完整流程时序图如下: