浅谈Activity启动过程
本篇博客参考资料:
探索7.x源码, 全面解析Activity启动框架 (1)
《Android开发艺术探索》——任玉刚
在日常的开发中,我们通常使用startActivity(Intent intent)
来启动一个新的Activity,我们能够如此简单的启动一个Activity要归功于Android开发团队完美的封装,屏蔽了Activity启动的底层细节,但是作为一个开发者,仅仅知道调用API是不够的,因此今天咱们就来好好聊聊一个Activity到底是怎么启动的。
首先从startActivity方法开始分析,startActivity有很多种重载方法,但是所有的重载方法最终都会调用startActivityForResult这个方法:
@Override
public void startActivity(Intent intent, @Nullable Bundle options) {
if (options != null) {
startActivityForResult(intent, -1, options);
} else {
startActivityForResult(intent, -1);
}
}
startActivityForResult的方法实现如下所示:
public void startActivityForResult(@RequiresPermission Intent intent, int requestCode,
@Nullable Bundle options) {
if (mParent == null) {
options = transferSpringboardActivityOptions(options);
Instrumentation.ActivityResult ar =
mInstrumentation.execStartActivity(
this, mMainThread.getApplicationThread(), mToken, this,
intent, requestCode, options);
.........
.........
}
我省略了部分对于今天要学习的内容不重要的代码,在startActivityForResult方法中我们关注的是mParent==null这部分逻辑。可以看到,在startActivityForResult方法中调用了Instrumentation类下的execStartActivity方法,这个方法中我们需要关注一个参数——mMainThread.getApplicationThread(),这个参数的类型是ApplicationThread,而ApplicationThread是ActivityThread的内部类,ApplicationThread和ActivityThread在Activity的启动过程中起着重要的作用,这个之后会讲到。
接着看Instrumentation内部的execStartActivity方法:
public ActivityResult execStartActivity(
Context who, IBinder contextThread, IBinder token, Activity target,
Intent intent, int requestCode, Bundle options) {
// ...
try {
// ...
int result = ActivityManagerNative.getDefault()
.startActivity(whoThread, who.getBasePackageName(), intent,
intent.resolveTypeIfNeeded(who.getContentResolver()),
token, target != null ? target.mEmbeddedID : null,
requestCode, 0, null, options); // 核心方法
// ...
} // ...
return null;
}
可以看到,启动Activity是由ActivityManagerNative.getDefault()下的startActivity方法完成的。ActivityManagerService(AMS)是ActivityManagerNative的子类,而ActivityManagerNative继承自Binder并且实现了IActivityManager接口(也是一个Binder),所以ActivityManagerNative就是一个Binder,自然其子类AMS也是Binder,同时AMS也是IActivityManager接口的具体实现类。
ActivityManagerNative.getDefault()方法返回的是一个IActivityManager类型的Binder对象,其具体实现类正是AMS,同时AMS在ActivityManagerNative中是以单例模式对外提供的。
所以execActivity内部机制实际上就是调用了AMS的startActivity方法来启动Activity,于是我们接着进入AMS内部的startActivity,看看其实现机制:
@Override
public final int startActivity(IApplicationThread caller, String callingPackage,
Intent intent, String resolvedTyoe, 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());
}
@Override
public final int startActivityAsUser(IApplicationThread caller, String callingPackage,
Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
int startFlags, ProfilerInfo profilerInfo, Bundle bOptions, int userId) {
// ...
return mActivityStarter.startActivityMayWait(caller, -1, callingPackage, intent,
resolvedType, null, null, resultTo, resultWho, requestCode, startFlags,
profilerInfo, null, null, bOptions, false, userId, null, null);
}
可以看到,Activity的启动又经过startActivityAsUser方法交给了ActivityStackSupervisor的startActivityMayWait方法,startActivityMayWait又调用了startActivityLocked方法,startActivityLocked又调用了startActivityUncheckedLocked方法,startActivityUncheckedLocked又调用了ActivityStack的resumeTopActivitiesLocked方法,这个时候Activity的启动过程从ActivityStackSupervisor转移到了ActivityStack,而在resumeTopActivitiesLocked方法中又调用了resumeTopActivityInnerLocked方法,resumeTopActivityInnerLocked方法又调用了ActivityStackSupervisor的startSpecificActivityLocked方法,于是Activity的启动过程从ActivityStack又回到了ActivityStackSupervisor。
这么一大串的调用确实是让人头昏眼花,但我们不用担心,我们只需关注最后回到ActivityStackSupervisor的这个方法:
void startSpecificActivityLocked(ActivityRecord r,
boolean andResume, boolean checkConfig) {
// 获取启动Activity的进程, 即Application
ProcessRecord app = mService.getProcessRecordLocked(r.processName,
r.info.applicationInfo.uid, true);
r.task.stack.setLaunchTime(r);
if (app != null && app.thread != null) {
try {
// ...
// 真正启动Activity的过程
realStartActivityLocked(r, app, andResume, checkConfig);
return;
}
// ...
}
// ...
}
在startSpecificActivityLocked方法中,终于看到了真正启动Activity的方法realStartActivityLocked,在这个方法中我们关注这样一段代码:
app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,
System.identityHashCode(r), r.info, new Configuration(mService.mConfiguration),
new Configuration(task.mOverrideConfig), r.compat, r.launchedFromPackage,
task.voiceInteractor, app.repProcState, r.icicle, r.persistentState, results,
newIntents, !andResume, mService.isNextTransitionForward(), profilerInfo);
app.thread的类型是IApplicationThread,而IApplicationThread是一个Binder类型的接口,这个接口中声明了大量的启动、停止Activity的方法,此外还包含了启动和停止Service的方法,因此IApplicationThread的实现者将拥有启动、停止Activity和Service的功能,而这个实现者就是ApplicationThread。
private class ApplicationThread extends ApplicationThreadNative
public abstract class ApplicationThreadNatibe extends Binder implements IApplicationThread
可以看到ApplicationThread继承自ApplicationThreadNative,而ApplicationThreadNatve继承自Binder同时实现了IApplicationThread接口。
于是在无数个方法和类中的传递后,Activity的启动过程最终来到了ApplicationThread中,如上面的代码所示,ApplicationThread通过scheduleLaunchActivity方法启动Activity:
public final void scheduleLaunchActivity(...) {
...
...
sendMessage(H.LAUNCH_ACTIVITY, r);
}
scheduleLaunchActivity启动Activity的过程很简单,就是发送一个启动Activity的消息交给Handler处理,这个Handler被取名为H,让我们看一下在Handler H中是如何对这个消息进行处理的:
//这个类太长,我只帖出了我们用到的部分
private class H extends Handler {
public void handleMessage(Message msg) {
if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what));
switch (msg.what) {
//这里处理LAUNCH_ACTIVITY消息类型
case LAUNCH_ACTIVITY: {
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityStart");
ActivityClientRecord r = (ActivityClientRecord)msg.obj;
r.packageInfo = getPackageInfoNoCheck(
r.activityInfo.applicationInfo, r.compatInfo);
//这里处理startActivity消息
handleLaunchActivity(r, null);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
} break;
case RELAUNCH_ACTIVITY: {
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityRestart");
ActivityClientRecord r = (ActivityClientRecord)msg.obj;
handleRelaunchActivity(r);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
} break;
case PAUSE_ACTIVITY:
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityPause");
handlePauseActivity((IBinder)msg.obj, false, msg.arg1 != 0, msg.arg2);
maybeSnapshot();
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
...
}
}
可以看到Handler H对”LAUNCH_ACTIVITY”消息的处理方式是调用ActivityThread下的handleLaunchActivity方法,handleLaunchActivity的源码如下:
private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent) {
...
if (localLOGV) Slog.v(
TAG, "Handling launch of " + r);
//performLaunchActivity真正完成了activity的调起,
//同时activity会被实例化,并且onCreate会被调用
Activity a = performLaunchActivity(r, customIntent);
if (a != null) {
r.createdConfig = new Configuration(mConfiguration);
Bundle oldState = r.state;
//目标activity的onResume会被调用
handleResumeActivity(r.token, false, r.isForward,
!r.activity.mFinished && !r.startsNotResumed);
...
}
}
终于发现performLaunchActivity方法最终完成了Activity的创建和启动,并且ActivityThread通过handleResumeActivity方法来调用Activity的onResume这一生命周期方法。
performLaunchActivity总结起来就是干了这几件事:
- 获取待启动的Activity的组件信息
- 创建Activity对象
- 尝试创建Application对象(若有则不再创建)
- 通过Activity的attach方法完成重要数据初始化
- 调用Activity的onCreate()生命周期方法
最后总结一下Activity的启动过程:当我们调用Activity类下的startActivity方法后,首先会调用startActivityForResult方法,这个方法内部接着会调用Instrumentation下的execStartActivity方法,execStartActivity内部是由AMS的startActivity方法实现的,从AMS的startActivity方法开始,Activity的启动过程就交给了ActivityStackSuperVisor,经过一系列反复调用,整个启动过程会分别交给ActivityStackSuperviosor和ActivityStack,最终又通过startSpecificActivityLocked方法重新交给ActivityStackSupervisor,startSpecificActivityLocked方法内部会调用readStartActivityLocked方法,这个方法就是真正开始启动Activity的方法。因为在这个方法中调用了ApplicationThread下的scheduleLaunchActivity方法,这个方法会发送一个启动Activity的消息给Handler H,Handler H会将Activity的启动交给ActivityThread下的handleLaunchActivity方法来实现,handleLaunchActivity方法的内部将Activity的启动交给了performLaunchActivity方法,Activity启动成功。
到此为止,整个Activity的启动过程算是告一段落了,需要注意的是,身为开发者我们不仅仅需要会调用api,还要对Android的内部机制进行一些‘适当’的了解,这个适当指的不是去深究Android的源码细节,而是要知道Android源码的大体流程,例如Activity的启动过程是怎样一个流程,会经过哪几个步骤,中间会有哪些重要的类参与这个过程,整个启动过程是怎样的一个思想。但是如果我们去研究这中间的每一行代码的话,不仅仅需要花费大量的时间,甚至还有可能得不偿失。