View的加載
Activity關(guān)聯(lián)window
ActivityThread#performLaunchActivity
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
...
Activity activity = null;
try {
java.lang.ClassLoader cl = appContext.getClassLoader();
// 通過(guò)反射創(chuàng)建出activity對(duì)象
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) {
...
}
try {
...
if (activity != null) {
...
// activity內(nèi)部初始化window實(shí)例PhoneWindow
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, r.configCallback);
...
// 調(diào)用Activity的onCreate方法
if (r.isPersistable()) {
mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
} else {
mInstrumentation.callActivityOnCreate(activity, r.state);
}
...
}
r.setState(ON_CREATE);
mActivities.put(r.token, r);
} catch (SuperNotCalledException e) {
throw e;
} catch (Exception e) {
...
}
return activity;
}
創(chuàng)建和初始化DecorView
Activity#setContentView
public void setContentView(View view) {
getWindow().setContentView(view);
initWindowDecorActionBar();
}
PhoneWindow#setContentView
public void setContentView(int layoutResID) {
if (mContentParent == null) {
installDecor(); --關(guān)鍵代碼
} else if (!hasFeature(FEATURE_CONTENT_TRANSITIONS)) {
mContentParent.removeAllViews();
}
if (hasFeature(FEATURE_CONTENT_TRANSITIONS)) {
final Scene newScene = Scene.getSceneForLayout(mContentParent, layoutResID,
getContext());
transitionTo(newScene);
} else {
// 將布局加載進(jìn)R.id.content的frameLayout中
mLayoutInflater.inflate(layoutResID, mContentParent);
}
// 通知Activity視圖發(fā)生改變
final Callback cb = getCallback();
if (cb != null && !isDestroyed()) {
cb.onContentChanged();
}
...
}
PhoneWindow#installDecor
private void installDecor() {
mForceDecorInstall = false;
if (mDecor == null) {
// 創(chuàng)建DecorView對(duì)象,這個(gè)就是根View,是一個(gè)FrameLayout
mDecor = generateDecor(-1);
mDecor.setDescendantFocusability(ViewGroup.FOCUS_AFTER_DESCENDANTS);
mDecor.setIsRootNamespace(true);
if (!mInvalidatePanelMenuPosted && mInvalidatePanelMenuFeatures != 0) {
mDecor.postOnAnimation(mInvalidatePanelMenuRunnable);
}
} else {
mDecor.setWindow(this);
}
if (mContentParent == null) {
// 通過(guò)窗口類(lèi)型獲取到布局id,創(chuàng)建出對(duì)應(yīng)的View,加載進(jìn)DecorView中(mDecor.onResourcesLoaded(mLayoutInflater, layoutResource);)
// 因?yàn)檫@個(gè)條件也是為什么代碼中寫(xiě)隱藏標(biāo)題欄要寫(xiě)在setContentView上面的原因
// 常規(guī)加載布局是screen_title.xml,上面ViewStub用來(lái)顯示ActionBar的,下面一個(gè)FrameLayout是title顯示標(biāo)題的,另一個(gè)FrameLayout為主要填充區(qū)域
// mContentParent就是這個(gè)id是R.id.content
mContentParent = generateLayout(mDecor);
...
}
}
screen_title.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:fitsSystemWindows="true">
<!-- Popout bar for action modes -->
<ViewStub android:id="@+id/action_mode_bar_stub"
android:inflatedId="@+id/action_mode_bar"
android:layout="@layout/action_mode_bar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="?attr/actionBarTheme" />
<FrameLayout
android:layout_width="match_parent"
android:layout_height="?android:attr/windowTitleSize"
style="?android:attr/windowTitleBackgroundStyle">
<TextView android:id="@android:id/title"
style="?android:attr/windowTitleStyle"
android:background="@null"
android:fadingEdge="horizontal"
android:gravity="center_vertical"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</FrameLayout>
<FrameLayout android:id="@android:id/content"
android:layout_width="match_parent"
android:layout_height="0dip"
android:layout_weight="1"
android:foregroundGravity="fill_horizontal|top"
android:foreground="?android:attr/windowContentOverlay" />
</LinearLayout>
由此可知,調(diào)用setContentView會(huì)創(chuàng)建和初始化DecorView。但是這個(gè)時(shí)候DecorView還沒(méi)有被WindowManager正式添加到Window中。
DecorView添加和顯示
public void handleResumeActivity(IBinder token, boolean finalStateRequest, boolean isForward,
String reason) {
...
// 執(zhí)行Activity的onResume方法
final ActivityClientRecord r = performResumeActivity(token, finalStateRequest, reason);
...
if (r.window == null && !a.mFinished && willBeVisible) {
r.window = r.activity.getWindow();
View decor = r.window.getDecorView();
// decorView隱藏
decor.setVisibility(View.INVISIBLE);
ViewManager wm = a.getWindowManager();
WindowManager.LayoutParams l = r.window.getAttributes();
a.mDecor = decor;
...
if (a.mVisibleFromClient) {
if (!a.mWindowAdded) {
a.mWindowAdded = true;
// 后面會(huì)著重講,里面初始化ViewRootImpl,通過(guò)WindowSession最終來(lái)完成Window的添加過(guò)程。
// 這個(gè)步驟完成DecorView添加進(jìn)window中
wm.addView(decor, l);
} else {
a.onWindowAttributesChanged(l);
}
}
} else if (!willBeVisible) {
if (localLOGV) Slog.v(TAG, "Launch " + r + " mStartedActivity set");
r.hideForNow = true;
}
cleanUpPendingRemoveWindows(r, false /* force */);
if (!r.activity.mFinished && willBeVisible && r.activity.mDecor != null && !r.hideForNow) {
...
// DecorView顯示,到這里Activity的視圖才能被用戶看到
if (r.activity.mVisibleFromClient) {
r.activity.makeVisible();
}
}
...
}
Activity#makeVisible
void makeVisible() {
if (!mWindowAdded) {
ViewManager wm = getWindowManager();
wm.addView(mDecor, getWindow().getAttributes());
mWindowAdded = true;
}
mDecor.setVisibility(View.VISIBLE);
}
Activity,Window,View關(guān)系
在onCreate方法之前,Activity調(diào)用attach方法創(chuàng)建Window。
Window通過(guò)setContentView創(chuàng)建DecorView,并將布局加載進(jìn)DecorView的R.id.content中,有標(biāo)題欄處理標(biāo)題欄。
在onResume方法之后,調(diào)用windowManager的addView方法,將DecorView添加進(jìn)window中。調(diào)用makeVisible方法將DecorView顯示出來(lái)。
ViewRootImpl
布局檢查機(jī)制:ViewRootImpl
View的繪制是由ViewRootImpl來(lái)負(fù)責(zé)的。每個(gè)應(yīng)用程序窗口的DecorView都有一個(gè)與之關(guān)聯(lián)的ViewRootImpl對(duì)象,這種關(guān)聯(lián)關(guān)系是由WindowManager來(lái)維護(hù)的。
ViewRootImpl初始化
ActivityThread#handleResumeActivity
調(diào)用wm.addView(decor, l);
參數(shù)是DecorView,窗口布局參數(shù)。
這個(gè)addView方法是在onResume方法之后調(diào)用。
WindowManager是對(duì)外提供的接口,實(shí)例類(lèi)是WindowManagerImpl。
WindowManagerImpl#addView
public void addView(@NonNull View view, @NonNull ViewGroup.LayoutParams params) {
applyDefaultToken(params);
mGlobal.addView(view, params, mContext.getDisplayNoVerify(), mParentWindow,
mContext.getUserId());
}
WindowManagerGlobal#addView
public void addView(View view, ViewGroup.LayoutParams params,
Display display, Window parentWindow, int userId) {
...
ViewRootImpl root;
View panelParentView = null;
synchronized (mLock) {
...
// 創(chuàng)建ViewRootImpl實(shí)例
root = new ViewRootImpl(view.getContext(), display);
view.setLayoutParams(wparams);
mViews.add(view);
mRoots.add(root);
mParams.add(wparams);
try {
// view是DecorView,這行代碼將開(kāi)始繪制view
root.setView(view, wparams, panelParentView, userId);
} catch (RuntimeException e) {
// BadTokenException or InvalidDisplayException, clean up.
if (index >= 0) {
removeViewLocked(index, true);
}
throw e;
}
}
}
View繪制
public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView,
int userId) {
synchronized (this) {
if (mView == null) {
...
//進(jìn)行View布局繪制
requestLayout();
...
try {
mOrigWindowType = mWindowAttributes.type;
mAttachInfo.mRecomputeGlobalAttributes = true;
collectViewAttributes();
adjustLayoutParamsForCompatibility(mWindowAttributes);
// 通過(guò)WindowSession最終來(lái)完成Window的添加過(guò)程。
// mWindowSession的類(lèi)型是IWindowSession,它是一個(gè)Binder對(duì)象,真正的實(shí)現(xiàn)類(lèi)是Session,也就是Window的添加過(guò)程是一次IPC調(diào)用。
// 在Session內(nèi)部會(huì)通過(guò)WMS來(lái)實(shí)現(xiàn)Window的添加
res = mWindowSession.addToDisplayAsUser(mWindow, mSeq, mWindowAttributes,
getHostVisibility(), mDisplay.getDisplayId(), userId, mTmpFrame,
mAttachInfo.mContentInsets, mAttachInfo.mStableInsets,
mAttachInfo.mDisplayCutout, inputChannel,
mTempInsets, mTempControls);
setFrame(mTmpFrame);
} catch (RemoteException e) {
mAdded = false;
mView = null;
mAttachInfo.mRootView = null;
inputChannel = null;
mFallbackEventHandler.setView(null);
unscheduleTraversals();
setAccessibilityFocus(null, null);
throw new RuntimeException("Adding window failed", e);
} finally {
if (restore) {
attrs.restore();
}
}
...
// 注意這里,ViewRootImpl實(shí)現(xiàn)ViewParent接口,這里將ViewRootImpl抽象為DecorView的父布局,注意只是抽象,ViewRootImpl并不是View
view.assignParent(this);
...
}
}
}
ViewRootImpl#requestLayout
public void requestLayout() {
if (!mHandlingLayoutInLayoutRequest) {
// 線程檢測(cè)
checkThread();
mLayoutRequested = true;
// 繪制方法doTraversal是在下次loop循環(huán)才去調(diào)用而不是立即調(diào)用
// doTraversal方法中調(diào)用performTraversals使ViewTree開(kāi)始View繪制
// 分別調(diào)用performMeasure,performLayout,performDraw,在其內(nèi)部又會(huì)分別調(diào)用View的measure,layout,draw方法
scheduleTraversals();
}
}