概要
在Android開發(fā)中,Activity可謂是最重要之一的組件了。分析和熟悉Activity的啟動流程,可幫助認(rèn)識整個Android系統(tǒng)全貌。這里主要分析基于Android7.0從startActivity到Activity頁面顯示這一過程。
1.涉及主要類:
android.app.Instrumentation.java
android.app.ActivityThread.java
android.app.ActivityManager.java
com.android.server.am.ActivityManagerService.java
com.android.internal.policy.PhoneWindon.java
com.android.internal.policy.DecorView.java
android.view.WindowManage.java
com.android.server.wm.WindowManagerService.java
2.流程圖:

具體流程
1.Activity.startActivityForResult()
/**
* @hide
*/
@Override
public void startActivityForResult(
String who, Intent intent, int requestCode, @Nullable Bundle options) {
...
Instrumentation.ActivityResult ar =
mInstrumentation.execStartActivity(
this, mMainThread.getApplicationThread(), mToken, who,
intent, requestCode, options);
...
}
cancelInputsAndStartExitTransition(options);
}
首先我們看看這個mInstrumentation.execStartActivity(this, mMainThread.getApplicationThread(), mToken, who,intent, requestCode, options)這個方法。其中第二個參數(shù)是ActivityThread類中的內(nèi)部類ApplicationThread,這個是IBinder的代理類,用戶接收ActivityMangageService的消息。
2.Instrumentation.execStartActivity()
public ActivityResult execStartActivity(
Context who, IBinder contextThread, IBinder token, Activity target,
Intent intent, int requestCode, Bundle options) {
...
try {
intent.migrateExtraStreamToClipData();
intent.prepareToLeaveProcess(who);
int result = ActivityManager.getService()
.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;
}
這個方法主要通過IPC方式發(fā)送消息給AMS(指ActivityManageService.java(下同)),從而調(diào)用startActivity(),這里就涉及到AMS服務(wù)了,在這過程中會進(jìn)行一系列的準(zhǔn)備,其中保存判斷被啟動的的Activity所在的進(jìn)程是否和當(dāng)前Activity所在的進(jìn)程一致,若不一致則會從zygote進(jìn)程fork一個進(jìn)程;還有比如Activity的啟動方式的判斷等。最終會通過Binder IPC調(diào)用ActivityThread.ApplicationThread中的scheduleLaunchActivity()方法
3.ActivityThread.ApplicationThread. scheduleLaunchActivity()
在這一步驟中會通過sendMessage(H.LAUNCH_ACTIVITY, r)發(fā)送消息給ActivityThread.H,從而調(diào)用handleLaunchActivity()方法;
4.ActivityThread.handleLaunchActivity()
private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent, String reason) {
//省略部分代碼
Activity a = performLaunchActivity(r, customIntent);
if (a != null) {
//省略部分代碼
handleResumeActivity(r.token, false, r.isForward,
!r.activity.mFinished && !r.startsNotResumed, r.lastProcessedSeq, reason);
//省略部分代碼
}
}
這里主要看performLaunchActivity()這個方法,這個里面會創(chuàng)建Activity的實例,然后在調(diào)用Activity.attach()方法,之后調(diào)用Activity的一系列生命周期方法。
5.Activity.attach()
final void attach(Context context, ActivityThread aThread,
Instrumentation instr, IBinder token, int ident,
Application application, Intent intent, ActivityInfo info,
CharSequence title, Activity parent, String id,
NonConfigurationInstances lastNonConfigurationInstances,
Configuration config, String referrer, IVoiceInteractor voiceInteractor,
Window window, ActivityConfigCallback activityConfigCallback) {
attachBaseContext(context);
mFragments.attachHost(null /*parent*/);
mWindow = new PhoneWindow(this, window, activityConfigCallback);
mWindow.setWindowControllerCallback(this);
mWindow.setCallback(this);
mWindow.setOnWindowDismissedCallback(this);
mWindow.getLayoutInflater().setPrivateFactory(this);
if (info.softInputMode != WindowManager.LayoutParams.SOFT_INPUT_STATE_UNSPECIFIED) {
mWindow.setSoftInputMode(info.softInputMode);
}
if (info.uiOptions != 0) {
mWindow.setUiOptions(info.uiOptions);
}
//省略部分代碼
}
這個方法參數(shù)比較多,我們主要看下對應(yīng)的Window的創(chuàng)建:通過代碼我們可以看到只要調(diào)用attach方法就會創(chuàng)建一個對應(yīng)的window,也就是說一個Activity對應(yīng)一個window(window只有個實現(xiàn)類就是PhoneWindow)。PhoneWindow創(chuàng)建的同時又會創(chuàng)建DecorView(相當(dāng)于是Activity的rootView)。
public class DecorView extends FrameLayout implements RootViewSurfaceTaker, WindowCallbacks
DecorView繼承與FrameLayout,查看PhoneWindow.java源碼你會發(fā)現(xiàn)會DecorView添加兩個子View:R.id.title和com.android.internal.R.id.content。到這里就可以知道Activity和Window的關(guān)系了:

6.Activity.makeVisible()
void makeVisible() {
if (!mWindowAdded) {
ViewManager wm = getWindowManager();
wm.addView(mDecor, getWindow().getAttributes());
mWindowAdded = true;
}
mDecor.setVisibility(View.VISIBLE);
}
執(zhí)行完attach之后緊接著會調(diào)用Activity中的相關(guān)生命周期方法onCreate()、onStart()和onResume()方法。之后就會執(zhí)行上面的makeVisible()方法,這里才是真正的開始繪制顯示Activity視圖。在這個方法中會調(diào)用windowManage添加window,最終會通過ViewRootImpl.java這個類的setView(),然后在通過Binder IPC和WindowManageService通信最終完成window的添加。
這里有個問題:當(dāng)我們每次去更新UI的時候都是通過ViewRootImpl去執(zhí)行更新以及檢查當(dāng)前執(zhí)行更新的線程。而ViewRootImpl的創(chuàng)建就是在執(zhí)行wm.addView()的時候創(chuàng)建的。所以在ViewRootImpl沒有創(chuàng)建之前是不會對線程進(jìn)程檢查及更新繪制UI的。
總結(jié)
通過對Activity的啟動過程及視圖的呈現(xiàn)分析,我們可以總結(jié)如下:
1、通過Binder IPC的方式和AMS通信完成Activity創(chuàng)建前的一系列準(zhǔn)備。若要啟動的這個Activity所在的進(jìn)程沒有啟動,那么AMS會通過Socket發(fā)送消息給Zygote,Zygote會fork出應(yīng)用程序進(jìn)程,并且通過反射創(chuàng)建這個應(yīng)用程序的ActivityThread,并且調(diào)用ActivityThread的main方法,此時這個應(yīng)用程序就啟動了;
2、在AMS完成準(zhǔn)備工作之后又以IPC的方式發(fā)送lunchActivity消息,ActivityThread.ApplicationThreah 收到消息之后,又通過handler機(jī)制發(fā)送LAUNCH_ACTIVITY消息給ActivityThread.H;
3、之后通過Instrumentation.newActivity()完成Activity的創(chuàng)建;
( Activity activity = (Activity)clazz.newInstance())
4、在創(chuàng)建完Activity實例之后會調(diào)用Activity.acctch()方法完成window和DecorView的創(chuàng)建,最終通過WindowManage.addView()完成對window的添加。