一、从setContentView(R.layout.activity_main);入手了解UI的绘制起始过程
1.Activity.java
public void setContentView(@LayoutRes int layoutResID) {
getWindow().setContentView(layoutResID);//①
initWindowDecorActionBar();
}
2.getWindow()拿到的是Window的实现类PhoneWindow
PhoneWindow源码:
@Override
public void setContentView(int layoutResID) {
// Note: FEATURE_CONTENT_TRANSITIONS may be set in the process of installing the window
// decor, when theme attributes and the like are crystalized. Do not check the feature
// before this happens.
if (mContentParent == null) {
installDecor();//②
}
……
mLayoutInflater.inflate(layoutResID, mContentParent);//⑥
}
private void installDecor() {
if (mDecor == null) {
mDecor = generateDecor();//③生成一个DecorView(继承的FrameLayout)
mDecor.setDescendantFocusability(ViewGroup.FOCUS_AFTER_DESCENDANTS);
mDecor.setIsRootNamespace(true);
if (!mInvalidatePanelMenuPosted && mInvalidatePanelMenuFeatures != 0) {
mDecor.postOnAnimation(mInvalidatePanelMenuRunnable);
}
}
if (mContentParent == null) {
mContentParent = generateLayout(mDecor);//④
}
protected ViewGroup generateLayout(DecorView decor) {//⑤
View in = mLayoutInflater.inflate(layoutResource, null);
decor.addView(in, new ViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT));
mContentRoot = (ViewGroup) in;
}
二、measure、layout、draw的三个执行流程
- 1.View.java类
measure:测量,测量自己有多大,如果是ViewGroup的话会同时测量里面的子控件的大小
layout:摆放viewgroup里面的子控件(view是不需要layout的)
draw:绘制UI
看View.java类的源码:
1.view的requestLayout()方法开始,递归地不断往上找父容器,最终找到DecorView
2.执行了DecorView的ViewRootImp类的performTranversal()方法
3.performTranversal(){
// Ask host how big it wants to be
performMeasure(childWidthMeasureSpec, childHeightMeasureSpec);
performLayout(lp, desiredWindowWidth, desiredWindowHeight);
performDraw();
}
4.
private void performMeasure(int childWidthMeasureSpec, int childHeightMeasureSpec) {
Trace.traceBegin(Trace.TRACE_TAG_VIEW, "measure");
try {
mView.measure(childWidthMeasureSpec, childHeightMeasureSpec);//测量最后是调用该方法
} finally {
Trace.traceEnd(Trace.TRACE_TAG_VIEW);
}
}
流程如下(如此完成一个view的绘制):
- 2.ViewGroup.java类
ViewGroup的绘制也是首先找到DecorView,接着在DecorView里面找到ViewGroup当作RootView,然后执行如下流程(在RootView里面递归):