Activity的启动过程分析
缘起
我们在平时开发中都知道通过这样的代码就可以启动一个act,如下Context.startActivity(intent)
,但是你偶尔有没有想过它内部是如何实现的,或者说系统究竟干了哪些事情,怎么这个act就显示在用户面前呢?作为一个资深工程师我觉得你起码应该想过这个问题,下面我们一起来梳理下整个流程,以下分析基于6.0源码。
在开始之前我还想啰嗦几句,其实启动一个act的过程,是一个标准的Android IPC过程,也就是通过Binder机制实现的跨进程通信,先预告下,后面慢慢细说。
过程分析
- 一般我们都是通过调用
Activity.startActivity(intent)
来启动一个act的,紧接着它会调用其内部的startActivityForResult(intent, -1, null )
方法,注意这里的requestCode==-1
,因为我们不需要返回result; - 接下来调用到了
Instrumentation.execStartActivity()
方法,它最终调用了如下代码:
execStartActivity()方法 - 上面的
ActivityManagerNative.getDefault().startActivity
实际通过Binder机制调到了
另一个进程中的AMS.startActivity
方法,代码如下:
server/am/ActivityManagerService.java
接下来在AMS这边的调用流程这里简要罗列下,具体实现细节可以参考源码,流程如下:
ActivityStackSupervisor.startActivityMayWait -->
ActivityStackSupervisor.startActivityLocked -->
ActivityStackSupervisor.startActivityUncheckedLocked -->
ActivityStack.resumeTopActivitiesLocked -->
ActivityStack.resumeTopActivityInnerLocked -->
ActivityStackSupervisor.startSpecificActivityLocked -->
ActivityStackSupervisor.realStartActivityLocked
最终在ActivityStackSupervisor.realStartActivityLocked
里有这样的代码:
app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken, System.identityHashCode(r), r.info, new Configuration(mService.mConfiguration),
new Configuration(stack.mOverrideConfig), r.compat, r.launchedFromPackage,
task.voiceInteractor, app.repProcState, r.icicle, r.persistentState, results,
newIntents, !andResume, mService.isNextTransitionForward(), profilerInfo);
这段代码很关键,这里app.thread
的类型为android.app.IApplicationThread,其源码大概是这个样子:
-
IApplicationThread的真正实现者就是客户端进程中ActivityThread的内部类ApplicationThread,我们去看眼其实现:
ApplicationThread实现
绕了一个大圈子,activity的启动流程终于又回到客户端进程了,我们看下ApplicationThread.scheduleLaunchActivity的实现:
@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) {
updateProcessState(procState, false);
ActivityClientRecord r = new ActivityClientRecord();
r.token = token;
r.ident = ident;
r.intent = intent;
r.referrer = referrer;
r.voiceInteractor = voiceInteractor;
r.activityInfo = info;
r.compatInfo = compatInfo;
r.state = state;
r.persistentState = persistentState;
r.pendingResults = pendingResults;
r.pendingIntents = pendingNewIntents;
r.startsNotResumed = notResumed;
r.isForward = isForward;
r.profilerInfo = profilerInfo;
r.overrideConfig = overrideConfig;
updatePendingConfiguration(curConfig);
sendMessage(H.LAUNCH_ACTIVITY, r);
}
可以看到代码主要是用传进来的参数构造了一个ActivityClientRecord实例,然后发送了一个LAUNCH_ACTIVITY的msg;
- 对此消息的处理实质是调用了
ActivityThread.handleLaunchActivity
方法,代码如下:
private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent) {
// If we are getting ready to gc after going to the background, well
// we are back active so skip it.
unscheduleGcIdler();
mSomeActivitiesChanged = true;
if (r.profilerInfo != null) {
mProfiler.setProfiler(r.profilerInfo);
mProfiler.startProfiling();
}
// Make sure we are running with the most recent config.
handleConfigurationChanged(null, null);
if (localLOGV) Slog.v(
TAG, "Handling launch of " + r);
// Initialize before creating the activity
WindowManagerGlobal.initialize();
Activity a = performLaunchActivity(r, customIntent);
if (a != null) {
r.createdConfig = new Configuration(mConfiguration);
Bundle oldState = r.state;
handleResumeActivity(r.token, false, r.isForward,
!r.activity.mFinished && !r.startsNotResumed);
if (!r.activity.mFinished && r.startsNotResumed) {
// The activity manager actually wants this one to start out
// paused, because it needs to be visible but isn't in the
// foreground. We accomplish this by going through the
// normal startup (because activities expect to go through
// onResume() the first time they run, before their window
// is displayed), and then pausing it. However, in this case
// we do -not- need to do the full pause cycle (of freezing
// and such) because the activity manager assumes it can just
// retain the current state it has.
try {
r.activity.mCalled = false;
mInstrumentation.callActivityOnPause(r.activity);
// We need to keep around the original state, in case
// we need to be created again. But we only do this
// for pre-Honeycomb apps, which always save their state
// when pausing, so we can not have them save their state
// when restarting from a paused state. For HC and later,
// we want to (and can) let the state be saved as the normal
// part of stopping the activity.
if (r.isPreHoneycomb()) {
r.state = oldState;
}
if (!r.activity.mCalled) {
throw new SuperNotCalledException(
"Activity " + r.intent.getComponent().toShortString() +
" did not call through to super.onPause()");
}
} catch (SuperNotCalledException e) {
throw e;
} catch (Exception e) {
if (!mInstrumentation.onException(r.activity, e)) {
throw new RuntimeException(
"Unable to pause activity "
+ r.intent.getComponent().toShortString()
+ ": " + e.toString(), e);
}
}
r.paused = true;
}
} else {
// If there was an error, for any reason, tell the activity
// manager to stop us.
try {
ActivityManagerNative.getDefault()
.finishActivity(r.token, Activity.RESULT_CANCELED, null, false);
} catch (RemoteException ex) {
// Ignore
}
}
}
通过其源码我们发现,它又将重任交给了performLaunchActivity方法,这个方法主要做了以下几件事情:
1. 从ActivityClientRecord中获取待启动act的组件信息;
2. 通过Instrumentation.newActivity方法使用ClassLoader创建act对象;
3. 通过LoadedApk.makeApplication方法创建Application对象,注意如果已经有Application对象的话是不会再次创建的;
4. 创建ComtextImpl对象,并调用Activity.attach方法完成一些重要数据的初始化操作;
5. 最终调用Activity.onCreate()方法;
至此,act的整个启动流程就走完了。
总结
平时对于我们开发人员来说,可能还是最后这块客户端部分的代码比较
有用,非常有助于我们的理解,特别是对performLaunchActivity的源码,有空的话还需要细细品味啊。
注:关于这里第5步更详细的文章见这里ActivityThread.handleLaunchActivity方法分析。