Activity启动流程浅析
我们经常通过下面的代码来显示启动一个Activity,但是在这简单的操作背后,你有没有想过TargetActivity的实例是何时被创建的呢?TargetActivity又是何时进入onCreate、onStart、onResume生命周期呢?TargetActivity的DecorView又是何时被测量、布局、绘制并显示的呢?本篇文章将带你逐步探索Activity的启动流程。
Intent intent = new Intent(this, TargetActivity.class);
startActivity(intent);
前
public void startActivity(Intent intent) {
this.startActivity(intent, null);
}
public void startActivity(Intent intent, @Nullable Bundle options) {
if (options != null) {
startActivityForResult(intent, -1, options);
} else {
// Note we want to go through this call for compatibility with
// applications that may have overridden the method.
startActivityForResult(intent, -1);
}
}
如上所示,位于Activity类中的startActivity方法有两个重载方法,它们最终都会调用startActivityForResult方法,我们看一下startActivityForResult方法:
public void startActivityForResult(@RequiresPermission Intent intent, int requestCode)
{
startActivityForResult(intent, requestCode, null);
}
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);
if (ar != null) {
mMainThread.sendActivityResult(
mToken, mEmbeddedID, requestCode, ar.getResultCode(),
ar.getResultData());
}
if (requestCode >= 0) {
// If this start is requesting a result, we can avoid making
// the activity visible until the result is received. Setting
// this code during onCreate(Bundle savedInstanceState) or onResume() will
// keep the activity hidden during this time, to avoid flickering.
// This can only be done when a result is requested because
// that guarantees we will get information back when the
// activity is finished, no matter what happens to it.
mStartedActivity = true;
}
cancelInputsAndStartExitTransition(options);
// TODO Consider clearing/flushing other event sources and events for child
// windows.
} else {
if (options != null) {
mParent.startActivityFromChild(this, intent, requestCode, options);
} else {
// Note we want to go through this method for compatibility with
// existing applications that may have overridden it.
mParent.startActivityFromChild(this, intent, requestCode);
}
}
}
通过上面的代码我们可以看到,startActivityForResult方法其实是通过调用Instrumentation的execStartActivity方法来完成Activity的启动操作的。但是在调用execStartActivity方法时会为其增加四个参数:this、mMainThread.getApplicationThread()、mToken以及this。下面简单介绍一下这四个参数:
- this:该参数被向上转型为Context,表示了这个Activity所在的上下文环境,用于获取应用的包名;
- mMainThread.getApplicationThread():该参数是一个ApplicationThread实例,被向上转型为IBinder,该参数在启动Activity过程中发挥着重要作用,下面会详细解释;
- mToken:mToken也是一个IBinder类型,在Activity执行attach的时候被赋值,它用来标示正在执行启动Activity操作的对象身份,通过使用mToken,我们就可以不必把Activity自身发送给ActivityManagerService来进行身份验证;
- this:该参数是Activity类型,表示了正在执行启动Activity操作的那个Activity,启动结果将由此Activity接收。
再看一下Instrumentation中的execStartActivity方法:
public Instrumentation.ActivityResult execStartActivity(
Context who, IBinder contextThread, IBinder token, Activity target,
Intent intent, int requestCode, Bundle options) {
IApplicationThread whoThread = (IApplicationThread) contextThread;
Uri referrer = target != null ? target.onProvideReferrer() : null;
if (referrer != null) {
intent.putExtra(Intent.EXTRA_REFERRER, referrer);
}
if (mActivityMonitors != null) {
synchronized (mSync) {
final int N = mActivityMonitors.size();
for (int i=0; i<N; i++) {
final Instrumentation.ActivityMonitor am = mActivityMonitors.get(i);
if (am.match(who, null, intent)) {
am.mHits++;
if (am.isBlocking()) {
return requestCode >= 0 ? am.getResult() : null;
}
break;
}
}
}
}
try {
intent.migrateExtraStreamToClipData();
intent.prepareToLeaveProcess(who);
int result = ActivityManagerNative.getDefault()
.startActivity(whoThread, who.getBasePackageName(), intent,
intent.resolveTypeIfNeeded(who.getContentResolver()),
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;
}
Instrumentation中通过ActivityManagerNative.getDefault().startActivity()方法完成Activity的启动。而ActivityManagerNative.getDefault()返回是一个IActicityManager类型的对象。下面看一下ActivityManagerNative.getDefault()方法:
static public IActivityManager getDefault() {
return gDefault.get();
}
private static final Singleton<IActivityManager> gDefault = new
Singleton<IActivityManager>() {
protected IActivityManager create() {
IBinder b = ServiceManager.getService("activity");
if (false) {
Log.v("ActivityManager", "default service binder = " + b);
}
IActivityManager am = asInterface(b);
if (false) {
Log.v("ActivityManager", "default service = " + am);
}
return am;
}
};
相信大家都知道ActivityManagerService,而ActivityManagerService继承自抽象类ActivityManagerNative,ActivityManagerNative又继承自Binder并实现了IActivityManager接口,也即ActivityManagerService是一个Binder对象。
IActivityManager接口继承自IIterface,因此IActivityManager其实是一个Binder类型的接口,而通过getDefault()方法获取的对象正是用于跟系统服务ActivityManagerService进行IPC通信。
上面可以看到gDefault是一个IActivityManager的单例,而gDefault.get()返回的正是asInterface(IBinder),也即是一个ActivityManagerProxy实例,用于在客户程序中发起IPC过程。因此,ActivityManagerNative.getDefault() .startActivity()的调用其实是一个IPC过程,服务端正是ActivityManagerService,startActivity方法如下:。
public int startActivity(IApplicationThread caller, String callingPackage, Intent
intent, String resolvedType, IBinder resultTo, String
resultWho, int requestCode, int startFlags, ProfilerInfo
profilerInfo, Bundle options) throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeInterfaceToken(IActivityManager.descriptor);
data.writeStrongBinder(caller != null ? caller.asBinder() : null);
data.writeString(callingPackage);
intent.writeToParcel(data, 0);
data.writeString(resolvedType);
data.writeStrongBinder(resultTo);
data.writeString(resultWho);
data.writeInt(requestCode);
data.writeInt(startFlags);
if (profilerInfo != null) {
data.writeInt(1);
profilerInfo.writeToParcel(data, Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
} else {
data.writeInt(0);
}
if (options != null) {
data.writeInt(1);
options.writeToParcel(data, 0);
} else {
data.writeInt(0);
}
mRemote.transact(START_ACTIVITY_TRANSACTION, data, reply, 0);
reply.readException();
int result = reply.readInt();
reply.recycle();
data.recycle();
return result;
}
看到这里,相信大家都很清楚了,Activity的启动过程的前半部分总结如下:
- 调用Activity类的startActivity或者starActivityForResult方法来启动Activity,最终调用会传递到Activity类中的startActivityForResult(@RequiresPermission Intent intent, int requestCode, @Nullable Bundle options)方法;
- startActivityForResult方法中会调用mInstrumentation.execStartActivity()方法,mInstrumentation是一个Instrumentation对象,在Activity执行attach时被赋值;
- Instrumentation中通过ActivityManagerNative.getDefault()来获取一个远程ActivityManagerService通过asInterface()转换为IActivityManager后的对象;
- 通过调用IActivityManager对象的startActivity方法,进行IPC调用,向ActivityManagerService请求启动Activity;
中
读者熟悉AIDL的话应该可以知道,在上面的startActivity方法中调用了mRemote.transact之后,就启动了IPC过程,然后onTransact中相应的代码会在服务端Binder线程池中执行,我们看一下onTransact方法:
public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
throws RemoteException {
switch (code) {
case START_ACTIVITY_TRANSACTION:
{
data.enforceInterface(IActivityManager.descriptor);
IBinder b = data.readStrongBinder();
IApplicationThread app = ApplicationThreadNative.asInterface(b);
String callingPackage = data.readString();
Intent intent = Intent.CREATOR.createFromParcel(data);
String resolvedType = data.readString();
IBinder resultTo = data.readStrongBinder();
String resultWho = data.readString();
int requestCode = data.readInt();
int startFlags = data.readInt();
ProfilerInfo profilerInfo = data.readInt() != 0
? ProfilerInfo.CREATOR.createFromParcel(data) : null;
Bundle options = data.readInt() != 0
? Bundle.CREATOR.createFromParcel(data) : null;
int result = startActivity(app, callingPackage, intent, resolvedType,
resultTo, resultWho, requestCode, startFlags, profilerInfo, options);
reply.writeNoException();
reply.writeInt(result);
return true;
}
//Other case。。
//此处省略3k行。。
}
该方法运行在system_process进程环境中,因此如果我们要debug跟踪此方法的话需要attach debugger到该进程。可以看到,在该方法中,会从data中读取相应的请求数据,然后调用ActivityManagerService中的startActivity方法。
看一下ActivityManagerService中的startActivity方法:
final int startActivity(Intent intent, ActivityStackSupervisor.ActivityContainer
container) {
enforceNotIsolatedCaller("ActivityContainer.startActivity");
final int userId = mUserController.handleIncomingUser(Binder.getCallingPid(),
Binder.getCallingUid(), mStackSupervisor.mCurrentUser, false,
ActivityManagerService.ALLOW_FULL_ONLY, "ActivityContainer", null);
// TODO: Switch to user app stacks here.
String mimeType = intent.getType();
final Uri data = intent.getData();
if (mimeType == null && data != null && "content".equals(data.getScheme())) {
mimeType = getProviderMimeType(data, userId);
}
container.checkEmbeddedAllowedInner(userId, intent, mimeType);
intent.addFlags(FORCE_NEW_TASK_FLAGS);
return mActivityStarter.startActivityMayWait(null, -1, null, intent, mimeType,
null, null, null, null, 0, 0, null,
null, null, null, false, userId,
container, null);
}
此处先暂时省略在ActivityStarter、ActivityStack、ActivityStackSupervisor中执行的一系列操作(后面的文章会详细分析ActivityManagerService所做的工作),直接看在ActivityStackSupervisor中的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类型,还记得我们在一开始的时候说过ApplicationThread在Activity启动过程中发挥着重要作用吗?在开始时通过mMainThread.getApplicationThread获得的ApplicationThread对象被向上转型为IBinder后通过IPC过程传递给ActivityManagerService。而app.thread就是该IBinder对象所对应的服务端本地对象。
再来看一下ApplicationThread,ApplicationThread是ActivityThread的内部类,它继承自抽象类ApplicationThreadNative,而ApplicationThreadNative则继承了Binder类并实现了IApplicationThread接口,在IApplicationThread接口中声明了大量的有关Activity以及Service生命周期的方法。那么,ApplicationThread也就是一个Binder,通过app.thread.scheduleLaunchActivity的调用也同样是一个IPC调用,而此时的服务方运行在进行启动Activity操作的进程中,通常也就是我们的应用程序所在的进程。
后
现在,Activity的启动过程已经重新切换到了起初的进程中,剩下的操作由ApplicationThread中的scheduleLaunchActivity方法完成。看一下scheduleLaunchActivity方法:
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) {
updateProcessState(procState, false);
ActivityClientRecord r = new ActivityClientRecord();
r.token = token;
r.ident = ident;
//……
sendMessage(H.LAUNCH_ACTIVITY, r);
}
可以看到scheduleLaunchActivity方法中只是简单的提取参数封装到一个ActivityClientRecord对象中,然后调用了sendMessage方法:
private void sendMessage(int what, Object obj, int arg1, int arg2, boolean async) {
if (DEBUG_MESSAGES) Slog.v(
TAG, "SCHEDULE " + what + " " + mH.codeToString(what)
+ ": " + arg1 + " / " + obj);
Message msg = Message.obtain();
Log.e("ActivityThreaddd", "sendMessage");
msg.what = what;
msg.obj = obj;
msg.arg1 = arg1;
msg.arg2 = arg2;
if (async) {
msg.setAsynchronous(true);
}
mH.sendMessage(msg);
}
在sendMessage方法中构造了一个Message,然后将其发送给mH。mH是ActivityThread中内部类H的实例,而H类继承自Handler,也即mH其实是一个Handler,剩下的处理流程将交由H的handleMessage来处理。
这里有一个问题,就是为什么要通过Handler来通信,而不是直接调用相应的处理逻辑?如果了解Binder的话,这个问题就很容易回答了,因为scheduleLaunchActivity方法的调用是一个IPC过程,也即scheduleLaunchActivity方法是在Binder线程池中执行的,因此需要使用Handler将任务切换到主线程。
现在看一下mH这个Handler的handleMessage方法:
public void handleMessage(Message msg) {
if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what));
switch (msg.what) {
case LAUNCH_ACTIVITY: {
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityStart");
final ActivityClientRecord r = (ActivityClientRecord) msg.obj;
r.packageInfo = getPackageInfoNoCheck(
r.activityInfo.applicationInfo, r.compatInfo);
handleLaunchActivity(r, null, "LAUNCH_ACTIVITY");
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
} break;
//other cases...
在handleMessage方法中通过handleLaunchActivity方法来完成Activity的启动:
private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent, String reason) {
//……
Activity a = performLaunchActivity(r, customIntent);
if (a != null) {
r.createdConfig = new Configuration(mConfiguration);
reportSizeConfigurations(r);
Bundle oldState = r.state;
handleResumeActivity(r.token, false, r.isForward, !r.activity.mFinished &&
!r.startsNotResumed, r.lastProcessedSeq, reason);
//……
}
在handleLaunchActivity中会通过performLaunchActivity方法完成Activity的onCreate、onStart过程,然后并会通过handleResumeActivity方法完成onResume过程,下面看一下performLaunchActivity方法:
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
//……
Activity activity = null;
try {
java.lang.ClassLoader cl = r.packageInfo.getClassLoader();
activity = mInstrumentation.newActivity(
cl, component.getClassName(), r.intent);
StrictMode.incrementExpectedActivityCount(activity.getClass());
r.intent.setExtrasClassLoader(cl);
r.intent.prepareToEnterProcess();
if (r.state != null) {
r.state.setClassLoader(cl);
}
} catch (Exception e) {
if (!mInstrumentation.onException(activity, e)) {
throw new RuntimeException(
"Unable to instantiate activity " + component
+ ": " + e.toString(), e);
}
}
try {
Application app = r.packageInfo.makeApplication(false, mInstrumentation);
//……
if (activity != null) {
//……
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);
if (customIntent != null) {
activity.mIntent = customIntent;
}
//……
if (r.isPersistable()) {
mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
} else {
mInstrumentation.callActivityOnCreate(activity, r.state);
}
//……
if (!r.activity.mFinished) {
activity.performStart();
r.stopped = false;
}
//……
return activity;
}
在performLaunchActivity方法中,首先创建Activity的实例,该过程在Instrumentation中由ClassLoader完成,然后通过makeApplication方法来创建Application实例,如果Application已经创建,那么在makeApplication方法中会直接返回该实例。之后,会执行Activity的attach方法, 为activity初始化一些重要的数据域。然后,通过callActivityOnCreate方法来调用Activity的performCreate方法,performCreate方法中会调用onCreate方法,最后会调用activity.performStart()方法,完成activity的onStart过程。
而Activity中的View的添加过程则是通过setContentView方法完成的,setContentView方法会调用PhoneWindow的setContentView方法,而PhoneWindow的setContentView方法中会通过installDecor方法来创建DecorView,然后通过LayoutInflater来将布局文件添加到DecorView的ContentParent中。
而Activity变为可见状态也是在handleResumeActivity方法里执行的,在通过调用performResumeActivity方法完成Activity的onResume之后,会调用通过WindowManager的addView来添加Window,在添加Window时会执行View的measure、layout以及draw过程,然后通过Activity的makeVisible方法使DecorView变为可见状态。