AndroidUI的绘制流程

前言

前些天研究自定义控件特意研究了下UI的绘制流程

1.首先说下Activity加载后的显示的View图

AndroidUI的绘制流程_第1张图片

2.然后我们从setContentView(R.layout.activity_main)入手,调用了Activity中的

public void setContentView(@LayoutRes int layoutResID) {

getWindow().setContentView(layoutResID);//1

initWindowDecorActionBar();

}

3.getWindow()拿到的是Window的实现类PhoneWindow

4,然后我们看PhoneWindow中的源码的setContentView 

--------------------------------------------------------------------------------------

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();//在这里创建了一个DecorView(继承自FrameLayout)2

}

……

mLayoutInflater.inflate(layoutResID, mContentParent);//初始化我们自己的布局  6

}

------------------------------------------------------------------------------

//decorView的具体创建过程

private void installDecor() {

if (mDecor == null) {

mDecor = generateDecor();//生成一个DecorView 3

mDecor.setDescendantFocusability(ViewGroup.FOCUS_AFTER_DESCENDANTS);

mDecor.setIsRootNamespace(true);

if (!mInvalidatePanelMenuPosted && mInvalidatePanelMenuFeatures != 0) {

mDecor.postOnAnimation(mInvalidatePanelMenuRunnable);

}

}

if (mContentParent == null) {

mContentParent = generateLayout(mDecor);//得到布局文件 4

}

----------------------------------------------------------------------------------------

protected ViewGroup generateLayout(DecorView decor) {//进行加载布局得到decorview中包含title和我们contentview的布局  5

View in = mLayoutInflater.inflate(layoutResource, null);

decor.addView(in, new ViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT));

mContentRoot = (ViewGroup) in;

}

----------------------------------------------------------------------------------

由此我们可以看出Activity加载View的流程是getWindow().setContentView(layoutResID)-->

installDecor()-->generateDecor()生成一个DecorView对象-->generateLayout(mDecor)得到DecorView加载的包括title和我们自己写的布局的也就是rootview-->generateLayout(DecorView decor)得到rootView-->mLayoutInflater.inflate(layoutResID, mContentParent)加载我们自己的布局


View的绘制

1.View的绘制执行measure,layout,draw三个执行流程

View类中

            measure:测量自己多大,如果是ViewGroup的话会同时测量子控件

           layout:摆放子控件的位置

           draw:绘制

从View.java类的源码中看到:

1.view的requestLayout()方法开始,递归不断的往上找父容器,最终找到DecorView

2.执行DecorView的ViewRootImp类中的performTransversal()方法

3.performTranversal(){

// Ask host how big it wants to be

performMeasure(childWidthMeasureSpec, childHeightMeasureSpec);

performLayout(lp, desiredWindowWidth, desiredWindowHeight);

performDraw();

}

然后执行相应的measure,layout.draw方法,当是Viewgroup会调用相应的view的measure,layout,draw,当是View的时候调用measure,layout,draw然后执行想用onmeasure,onlayout,ondraw来进行相应的绘制

再说一下View的measure的测量规格MeasureSpec

1.mode

              1)EXACTLY:精确的,例如我们写的一个确定值50dp

              2)AT_MOST:根据父容器当前的大小,结合你指定的尺寸参考值来考虑你应该是多大尺寸,需要计算(Match_parent,wrap_content就是属于这种)

              3)UPSPECIFIED:最多的意思。根据当前的情况,结合你制定的尺寸参考值来考虑,在不超过父容器给你限定的只存的前提下,来测量你的一个恰好的内容尺寸。用的比较少,一般见于ScrollView,ListView(大小不确定,同时大小还是变的。会通过多次测量才能真正决定好宽高。)

2.value:宽高的值

你可能感兴趣的:(AndroidUI的绘制流程)