繪製流程概覽
Android程序啓動 -> Activity加載並調用生命週期onCreate -> Activity調用setContentView -> UI繪製
Android啓動流程分析
我們都知道Android程序的啓動入口是ActivityThread.main函數,那麼看一看main函數是如何進行啓動的。
ActivityThread.class
public static void main(String[] args) {
…
ActivityThread thread = new ActivityThread();
thread.attach(false);
…
}
private void attach(boolean system) {
…
final IActivityManager mgr = ActivityManager.getService();
try {
mgr.attachApplication(mAppThread);
} catch (RemoteException ex) {
throw ex.rethrowFromSystemServer();
}
…
}
由上面的源碼可知,我們在main函數中做了兩件事情:
- 生成一個ActivityThread對象
- 調用該對象的attach方法
在attach方法中,也做了兩件事情:
- 獲取了IActivityManager的對象實例
- 執行該對象的attachApplication方法
通過ActivityManager.getService()獲取到Activity管理器接口對象,那麼如何拿到的呢?我們來看下源碼實現:
ActivityManager.class
/**
* @hide
*/
public static IActivityManager getService() {
return IActivityManagerSingleton.get();
}
private static final Singleton<IActivityManager> IActivityManagerSingleton =
new Singleton<IActivityManager>() {
@Override
protected IActivityManager create() {
final IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE);
final IActivityManager am = IActivityManager.Stub.asInterface(b);
return am;
}
};
- 服務管理器通過getService拿到了ActivityService 的IBinder對象,通過跨進程獲取到am對象。
- mgr.attachApplication(mAppThread)是將ApplicationThread和ActivityManagertService相關聯。
在APP進程啓動之後,AMS便會跨binder調用到ApplicationThread的scheduleLaunchActivity,啓動Activity。
詳細的介紹請參照深入理解Activity——Token之旅
通過上面的分析,我們知道ApplicationThread這個對象在啓動過程中起着至關重要的作用,來看下它的源碼:
ApplicationThread類裏面都幹了什麼事情?
ApplicationThread.class
private class ApplicationThread extends IApplicationThread.Stub {
public final void schedulePauseActivity(IBinder token, boolean finished, ...
public final void scheduleStopActivity(IBinder token, boolean showWindow, ...
@Override public final void scheduleLaunchActivity(Intent intent, IBinder token, int ident, ...
...
如上圖所示,一堆的schedule方法,按照字面翻譯,我們可以猜測出,這個是在Activity狀態變化時去調用的方法。
在諸多的schedule方法裏面,根據註釋得知,scheduleLaunchActivity是在Activity加載的時候調用,我們來看一下:
ApplicationThread.class
// we use token to identify this activity without having to send the
// activity itself back to the activity manager. (matters more with ipc)
@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();
...
updatePendingConfiguration(curConfig);
sendMessage(H.LAUNCH_ACTIVITY, r);
}
根據代碼我們可以分析
- 創建了ActivityClientRecord對象
- 將ActivityClientRecord對象以及標誌位LAUNCH_ACTIVITY發送出去
ApplicationThread.class
private void sendMessage(int what, Object obj) {
sendMessage(what, obj, 0, 0, false);
}
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();
msg.what = what;
msg.obj = obj;
msg.arg1 = arg1;
msg.arg2 = arg2;
if (async) {
msg.setAsynchronous(true);
}
mH.sendMessage(msg);
}
final H mH = new H();
private class H extends Handler {
...
}
通過以上代碼可以知道,將創建的ActivityClientRecord對象以及標誌位通過handler發送出去,那我們順着找到mH的handleMessage方法
private class H extends Handler {
...
public void handleMessage(Message msg) {
if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what));
switch (msg.what) {
case LAUNCH_ACTIVITY: {
...
final ActivityClientRecord r = (ActivityClientRecord) msg.obj;
...
handleLaunchActivity(r, null, "LAUNCH_ACTIVITY");
...
} break;
...
}
...
}
private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent, String reason) {
...
Activity a = performLaunchActivity(r, customIntent);
...
}
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
...
if (r.isPersistable()) {
mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
} else {
mInstrumentation.callActivityOnCreate(activity, r.state);
}
...
}
對應着LAUNCH_ACTIVITY,調用到了handleLaunchActivity函數-> performLaunchActivity函數,在performLaunchActivity函數中,我們可以看到 mInstrumentation.callActivityOnCreate的字樣,猜的沒錯的話,這就是調用Activity的onCreate函數的入口了,我們看下源碼:
Instrumentation.class
/**
* Perform calling of an activity's {@link Activity#onCreate}
* method. The default implementation simply calls through to that method.
* @param activity The activity being created.
* @param icicle The previously frozen state (or null) to pass through to
* @param persistentState The previously persisted state (or null)
*/
public void callActivityOnCreate(Activity activity, Bundle icicle,
PersistableBundle persistentState) {
prePerformCreate(activity);
activity.performCreate(icicle, persistentState);
postPerformCreate(activity);
}
Activity.class
final void performCreate(Bundle icicle) {
performCreate(icicle, null);
}
final void performCreate(Bundle icicle, PersistableBundle persistentState) {
...
if (persistentState != null) {
onCreate(icicle, persistentState);
} else {
onCreate(icicle);
}
...
}
public void onCreate(@Nullable Bundle savedInstanceState,
@Nullable PersistableBundle persistentState) {
onCreate(savedInstanceState);
}
總結一下調用關係,Instrumentation. callActivityOnCreate-> Activity. performCreate->Activity.onCreate。
到此爲止,我們的整個APP已經成功啓動啦~
總結一下:
2.Activity調用setContentView做了什麼?
敬請期待