第10章:Activity启动流程源码解析:从startActivity到onCreate的完整调用链
各位同学,今天我们来啃一块硬骨头——Activity的启动流程。说实话,这个流程我前前后后看了不下十遍,每次看都有新收获。你想想看,一个简单的startActivity()调用,背后竟然牵扯到Instrumentation、ActivityThread、AMS三大核心类,跨进程通信、Binder机制、生命周期调度全用上了。
我个人习惯把启动流程分成三个阶段来看:
- 应用内阶段:从
startActivity到Instrumentation,再到AMS - AMS处理阶段:进程创建、ActivityRecord管理、栈调度
- 应用内回调阶段:从
ActivityThread到onCreate
咱们今天就重点剖析第一阶段和第三阶段,AMS那块我会在后续章节单独展开。
10.1 起点:startActivity()到底干了什么?
我们先从最熟悉的入口开始。你平时写startActivity(intent),其实它内部调用了startActivityForResult()。嗯,这里要注意,如果你传了requestCode,系统会帮你处理回调;如果没传,默认是-1。
// Activity.java
@Override
public void startActivity(Intent intent) {
this.startActivity(intent, null);
}
@Override
public void startActivity(Intent intent, @Nullable Bundle options) {
if (options != null) {
startActivityForResult(intent, -1, options);
} else {
startActivityForResult(intent, -1);
}
}
看到没?最终都走到startActivityForResult。这里有个细节——mMainThread是什么?它就是ActivityThread的实例,每个应用进程只有一个。
public void startActivityForResult(@RequiresPermission Intent intent, int requestCode,
@Nullable Bundle options) {
if (mParent == null) {
// 核心调用
Instrumentation.ActivityResult ar =
mInstrumentation.execStartActivity(
this, mMainThread.getApplicationThread(), mToken, this,
intent, requestCode, options);
// ...
}
}
这里我当年踩过一个坑:mToken是什么?它是IBinder类型,代表当前Activity在AMS中的令牌。AMS通过这个token来识别是哪个Activity发起的请求。说白了,这就是一个跨进程的身份凭证。
10.2 Instrumentation:幕后总指挥
接下来进入Instrumentation。这个类很多人不熟悉,但它其实是Activity生命周期的总调度器。我建议你把Instrumentation理解成「Android系统的导演」,它负责协调Activity的创建、启动、销毁等所有动作。
// Instrumentation.java
public ActivityResult execStartActivity(
Context who, IBinder contextThread, IBinder token, Activity target,
Intent intent, int requestCode, Bundle options) {
// 1. 获取ApplicationThread(Binder服务端)
IApplicationThread whoThread = (IApplicationThread) contextThread;
// 2. 检查ActivityMonitor(用于测试)
if (mActivityMonitors != null) {
synchronized (mSync) {
for (int i = mActivityMonitors.size() - 1; i >= 0; i--) {
// ...
}
}
}
// 3. 通过AMS代理发起跨进程调用
int result = ActivityManager.getService().startActivity(
whoThread, who.getBasePackageName(), intent,
intent.resolveTypeIfNeeded(who.getContentResolver()),
token, target != null ? target.mEmbeddedID : null,
requestCode, 0, null, options);
// ...
}
关键点来了:ActivityManager.getService()返回的是IActivityManager的Binder代理对象。这个代理对象通过ServiceManager获取到AMS的Binder引用。也就是说,从这一刻起,调用就跨进程了。
核心理解:Instrumentation.execStartActivity()是应用进程向系统进程发起请求的桥梁。它把ApplicationThread(应用端的Binder服务)传给AMS,让AMS后续能回调应用进程。
10.3 AMS:系统大管家
AMS收到请求后,会做一系列复杂的校验和调度。这里我只说关键路径,完整的AMS逻辑我们后面专门开一章讲。
// ActivityManagerService.java
@Override
public final int startActivity(IApplicationThread caller, String callingPackage,
Intent intent, String resolvedType, IBinder resultTo, String resultWho,
int requestCode, int startFlags, ProfilerInfo profilerInfo, Bundle options) {
return startActivityAsUser(caller, callingPackage, intent, resolvedType, resultTo,
resultWho, requestCode, startFlags, profilerInfo, options,
UserHandle.getCallingUserId());
}
AMS会做以下几件事:
- 检查权限:调用方是否有启动目标Activity的权限
- 解析Intent:通过
PackageManager找到目标Activity - 检查进程:目标Activity所在的进程是否已启动
- 创建ActivityRecord:在AMS中记录这个Activity的信息
- 栈管理:决定Activity放在哪个Task中
如果目标进程还没启动,AMS会通过Process.start()创建新进程。进程创建完成后,会调用ActivityThread.main(),然后通过attach()方法把ApplicationThread注册到AMS。
避坑指南:我曾经在分析一个ANR问题时,发现AMS在等待目标进程启动时超时了。原因是目标进程的Application.onCreate()里做了太多耗时操作。记住,AMS等待进程启动是有超时时间的,默认10秒。
10.4 ActivityThread:应用进程的主心骨
当AMS准备好一切后,它会通过ApplicationThread回调应用进程。这个回调是Binder调用,发生在Binder线程池中。
// ActivityThread.java
private class ApplicationThread extends IApplicationThread.Stub {
@Override
public final void scheduleLaunchActivity(Intent intent, IBinder token, int ident,
ActivityInfo info, Configuration curConfig, Configuration overrideConfig,
CompatibilityInfo compatInfo, String referrer, IVoiceInteractor voiceInteractor,
int procState, Bundle state, PersistableBundle persistentState,
List<ResultInfo> pendingResults, List<ReferrerIntent> pendingNewIntents,
boolean notResumed, boolean isForward, ProfilerInfo profilerInfo, ClientTransactionHandler client) {
// 封装成ActivityClientRecord
ActivityClientRecord r = new ActivityClientRecord();
r.token = token;
r.ident = ident;
r.intent = intent;
r.activityInfo = info;
// ...
// 发送消息到主线程Handler
sendMessage(H.LAUNCH_ACTIVITY, r);
}
}
这里有个设计精妙之处:scheduleLaunchActivity是在Binder线程中执行的,但它通过sendMessage把任务交给了主线程的Handler。为什么要这么做?因为Activity的生命周期回调必须在主线程执行,而Binder线程不是主线程。
10.5 H类:主线程的消息调度器
H是ActivityThread的内部类,继承自Handler。它负责处理所有来自AMS的消息。
// ActivityThread.java
private class H extends Handler {
public static final int LAUNCH_ACTIVITY = 100;
public static final int PAUSE_ACTIVITY = 101;
// ... 还有很多
public void handleMessage(Message msg) {
switch (msg.what) {
case LAUNCH_ACTIVITY: {
// 从Message中取出ActivityClientRecord
ActivityClientRecord r = (ActivityClientRecord) msg.obj;
// 调用handleLaunchActivity
handleLaunchActivity(r, null, "LAUNCH_ACTIVITY");
} break;
}
}
}
你看,LAUNCH_ACTIVITY消息被分发到handleLaunchActivity方法。这个方法会做三件大事:
- 通过
performLaunchActivity创建Activity实例 - 调用
Activity.onCreate() - 通过
handleResumeActivity触发onResume()
10.6 最终章:performLaunchActivity与onCreate
终于到了创建Activity实例的环节。这里我建议你重点关注performLaunchActivity的实现:
// ActivityThread.java
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
// 1. 获取ActivityInfo
ActivityInfo aInfo = r.activityInfo;
if (r.packageInfo == null) {
r.packageInfo = getPackageInfo(aInfo.applicationInfo, r.compatInfo,
Context.CONTEXT_INCLUDE_CODE);
}
// 2. 通过ClassLoader创建Activity实例
java.lang.ClassLoader cl = r.packageInfo.getClassLoader();
Activity activity = r.packageInfo.getActivityFactory().newActivity(cl, aInfo.name, r.intent);
// 3. 创建Application(如果还没创建)
Application app = r.packageInfo.makeApplication(false, mInstrumentation);
// 4. 创建ContextImpl
ContextImpl appContext = createBaseContextForActivity(r, activity);
// 5. 将Activity与ContextImpl、Application关联
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, r.configCallback,
r.assistToken);
// 6. 调用onCreate
if (r.isPersistable()) {
mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
} else {
mInstrumentation.callActivityOnCreate(activity, r.state);
}
// 7. 设置Activity的状态为已创建
r.activity = activity;
r.stopped = true;
mActivities.put(r.token, r);
return activity;
}
看到第2步了吗?Activity是通过ClassLoader反射创建的。这意味着你的Activity类必须有一个无参构造器。我记得有一次,我在Activity里加了一个带参数的构造器,结果运行时直接崩溃了。嗯,这个坑我帮你们踩过了。
第6步调用了Instrumentation.callActivityOnCreate(),最终会调用到Activity.performCreate(),然后才是onCreate()。
// Instrumentation.java
public void callActivityOnCreate(Activity activity, Bundle icicle) {
prePerformCreate(activity);
activity.performCreate(icicle);
postPerformCreate(activity);
}
// Activity.java
final void performCreate(Bundle icicle) {
restoreHasCurrentPermissionRequest(icicle);
onCreate(icicle);
mActivityTransitionState.readState(icicle);
performCreateCommon();
}
至此,onCreate()终于被调用了。从startActivity()到onCreate(),经历了应用进程→AMS→应用进程的跨进程通信,涉及了Binder、Handler、反射等核心技术。
总结一下调用链:
startActivity()
→ startActivityForResult()
→ Instrumentation.execStartActivity()
→ AMS.startActivity() [跨进程]
→ AMS处理(权限、进程、栈)
→ ApplicationThread.scheduleLaunchActivity() [跨进程回调]
→ H.handleMessage(LAUNCH_ACTIVITY)
→ handleLaunchActivity()
→ performLaunchActivity()
→ ClassLoader.newInstance() [反射创建Activity]
→ activity.attach() [关联Context]
→ Instrumentation.callActivityOnCreate()
→ Activity.performCreate()
→ Activity.onCreate() [你终于等到了]
10.7 面试官常问的几个点
最后,我总结几个面试中经常被问到的问题,你们可以自己思考一下:
| 问题 | 核心答案 |
|---|---|
| 为什么需要Instrumentation? | Instrumentation是Activity生命周期的总调度器,它让系统可以在Activity创建前后插入监控逻辑(比如测试框架的ActivityMonitor) |
| ApplicationThread的作用? | 它是应用进程暴露给AMS的Binder接口,AMS通过它来调度应用进程的Activity生命周期 |
| 为什么用Handler而不是直接回调? | 因为AMS的回调发生在Binder线程,而Activity生命周期必须在主线程执行。Handler负责线程切换 |
| Activity实例是谁创建的? | ActivityThread通过ClassLoader反射创建,不是AMS创建的。AMS只负责调度决策 |
注意事项:以上分析基于Android 10(API 29)的源码。不同版本的Android在细节上可能有差异,比如Android 12引入了ClientTransaction来统一管理生命周期事务。但核心思想是一致的。
好了,这一章的内容就到这里。下一章我们会深入AMS内部,看看它到底是怎么管理Activity栈的。到时候我会分享一个我在做多窗口适配时遇到的真实案例,保证精彩。