緣起
我們在平時(shí)開發(fā)中都知道通過這樣的代碼就可以啟動(dòng)一個(gè)act,如下Context.startActivity(intent),但是你偶爾有沒有想過它內(nèi)部是如何實(shí)現(xiàn)的,或者說系統(tǒng)究竟干了哪些事情,怎么這個(gè)act就顯示在用戶面前呢?作為一個(gè)資深工程師我覺得你起碼應(yīng)該想過這個(gè)問題,下面我們一起來梳理下整個(gè)流程,以下分析基于6.0源碼。
在開始之前我還想啰嗦幾句,其實(shí)啟動(dòng)一個(gè)act的過程,是一個(gè)標(biāo)準(zhǔn)的Android IPC過程,也就是通過Binder機(jī)制實(shí)現(xiàn)的跨進(jìn)程通信,先預(yù)告下,后面慢慢細(xì)說。
過程分析
- 一般我們都是通過調(diào)用
Activity.startActivity(intent)來啟動(dòng)一個(gè)act的,緊接著它會(huì)調(diào)用其內(nèi)部的startActivityForResult(intent, -1, null )方法,注意這里的requestCode==-1,因?yàn)槲覀儾恍枰祷豶esult; - 接下來調(diào)用到了
Instrumentation.execStartActivity()方法,它最終調(diào)用了如下代碼:
execStartActivity()方法 - 上面的
ActivityManagerNative.getDefault().startActivity實(shí)際通過Binder機(jī)制調(diào)到了
另一個(gè)進(jìn)程中的AMS.startActivity方法,代碼如下:
server/am/ActivityManagerService.java
接下來在AMS這邊的調(diào)用流程這里簡要羅列下,具體實(shí)現(xiàn)細(xì)節(jié)可以參考源碼,流程如下:
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);
這段代碼很關(guān)鍵,這里app.thread的類型為android.app.IApplicationThread,其源碼大概是這個(gè)樣子:

-
IApplicationThread的真正實(shí)現(xiàn)者就是客戶端進(jìn)程中ActivityThread的內(nèi)部類ApplicationThread,我們?nèi)タ囱燮鋵?shí)現(xiàn):
ApplicationThread實(shí)現(xiàn)
繞了一個(gè)大圈子,activity的啟動(dòng)流程終于又回到客戶端進(jìn)程了,我們看下ApplicationThread.scheduleLaunchActivity的實(shí)現(xiàn):
@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);
}
可以看到代碼主要是用傳進(jìn)來的參數(shù)構(gòu)造了一個(gè)ActivityClientRecord實(shí)例,然后發(fā)送了一個(gè)LAUNCH_ACTIVITY的msg;
- 對此消息的處理實(shí)質(zhì)是調(diào)用了
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
}
}
}
通過其源碼我們發(fā)現(xiàn),它又將重任交給了performLaunchActivity方法,這個(gè)方法主要做了以下幾件事情:
1. 從ActivityClientRecord中獲取待啟動(dòng)act的組件信息;
2. 通過Instrumentation.newActivity方法使用ClassLoader創(chuàng)建act對象;
3. 通過LoadedApk.makeApplication方法創(chuàng)建Application對象,注意如果已經(jīng)有Application對象的話是不會(huì)再次創(chuàng)建的;
4. 創(chuàng)建ComtextImpl對象,并調(diào)用Activity.attach方法完成一些重要數(shù)據(jù)的初始化操作;
5. 最終調(diào)用Activity.onCreate()方法;
至此,act的整個(gè)啟動(dòng)流程就走完了。
總結(jié)
平時(shí)對于我們開發(fā)人員來說,可能還是最后這塊客戶端部分的代碼比較
有用,非常有助于我們的理解,特別是對performLaunchActivity的源碼,有空的話還需要細(xì)細(xì)品味啊。
注:關(guān)于這里第5步更詳細(xì)的文章見這里ActivityThread.handleLaunchActivity方法分析。


