ViewRoot
ViewRoot是連接WindowManager和DecorView的紐帶,View的measure,layout和draw都是ViewRoot來完成的
- 首先通過WindowManager將DecorView添加到Window中,與此同時將ViewRootImpl對象通過setView將DecorView關聯起來.
//WindowManagerGlobal.java
public void addView(View view, ViewGroup.LayoutParams params,
Display display, Window parentWindow) {
//...省略部分代碼
ViewRootImpl root;
View panelParentView = null;
synchronized (mLock) {
//...省略部分代碼
root = new ViewRootImpl(view.getContext(), display);
view.setLayoutParams(wparams);
mViews.add(view);
mRoots.add(root);
mParams.add(wparams);
// do this last because it fires off messages to start doing things
try {
//將DecorView關聯起來
root.setView(view, wparams, panelParentView);
} catch (RuntimeException e) {
// BadTokenException or InvalidDisplayException, clean up.
if (index >= 0) {
removeViewLocked(index, true);
}
throw e;
}
}
}
- 在加載到Window之前,其ViewRootImpl內部會通過requestLayout方法來布局整個DecorView樹,最終調用performTravels,依次執行DecorView的measure、layout、draw三大過程.
private void performTraversals() {
//...省略部分代碼
performMeasure(childWidthMeasureSpec, childHeightMeasureSpec);
//...省略部分代碼
performLayout(lp, mWidth, mHeight);
//...省略部分代碼
performDraw();
//...省略部分代碼
}
Measure
specSize: 32位int的高2位
specMode: 其余30位
Mode 三種模式:
EXACTLY: 精確模式
父View對子view有精確的大小,大小就是specSize.
對應于MACTCH_PARENT和具體數值.
AT_MOST:最大模式
父View對子view最大值有要求,大小就是specSize.
對應于WRAP_CONTENT
UNSPECIFIED
layout
如果子View是純View,那么在onLayout里,什么都不做.
如果是ViewGroup,那么在onLayout里,首先需要遍歷調用所有子view的layout方法,讓子View完成自我布局,依次遞歸.
draw方法里流程
drawBackground 繪制背景
onDraw 繪制自己
dispatchDraw 繪制子view
onDrawScrollBars 繪制裝飾