View的绘制流程——第二篇

activity.getlayoutinflater

getWindow(PhoneWindow).getlayoutinflater

初始化:
PhoneWindow
public PhoneWindow(Context context) {
super(context);
mLayoutInflater = LayoutInflater.from(context);
}

LayoutInflater
LayoutInflater LayoutInflater =
(LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);

解析 layoutinflater.inflate
四个重载方法

重点在于:
LayoutInflater.inflate(XmlPullParser parser, @Nullable ViewGroup root, boolean attachToRoot)

这个函数里面的逻辑:

前传:将root节点先赋值给result
1.寻找根节点,如果既不是 开始标签 也不是 结束标签 一直循环,解析器指向下一个标签一直到跳出循环为止

2.跳出循环之后,对type进行检查,正常的流程肯定是先遇到 开始标签,如果不是,抛出布局异常,提示没有找到 start tag

3.获取到当前解析器指向的标签名称name

4.如果是可调式模式,打印出当前的根节点

5.如果name是merge的话,也就是start tag是,说明一定需要绑定到一个爸爸上面
【1】如果此时爸爸是空的,或者需要绑定的标识符是false,那么就会出现异常
" can be used only with a valid "
+ "ViewGroup root and attachToRoot=true"
【2】如果爸爸和标识符都是正常的,那么继续使用递归的方式,遍历它的所有孩子

void rInflate(XmlPullParser parser, View parent, Context context, AttributeSet attrs, boolean finishInflate)
1.获取解析器当前元素的深度
Outside startTag 0
startTag 1
2
2
endTag 1
OutSide endTag 0
2.如果当前的节点不是endtag或者深度大于第一次获取的depth, 同时当前的type不是END_DOCUMENT(针对XML文档),进入循环
如果不是starttag,进入下一轮循环
获取当前解析器的元素名称,
TAG_REQUEST_FOCUS:???
TAG_TAG:为设置parent设置tag
TAG_INCLUDE:如果当前的getDepth是0的话,那么就会抛出异常,根节点不能是标签
如果不是的话,首先获取到爸爸的layoutParams,然后将其设置给子View,子View再去遍历自己的孩子,遍历之后 爸爸将子View加入到自己的孩子当中。
TAG_MERGE:如果是抛出异常,必须是根节点才能是merge标签,现在遍历都是子View
其他情况:首先创建出子View,拿到爸爸的布局参数,继续遍历自己的子View,遍历之后,爸爸将其加入到自己的孩子当中。

6.如果name不是merge的话,
【1】创建出子 View的实例(创建子View的时候,用到了工厂模式)
【2】如果爸爸不是null,获取到爸爸的布局参数,如果不需要绑定到爸爸上,那么将参数设置给子View
【3】子 View去遍历自己的孩子
【4】如果爸爸不是null而且需要去将子View绑定在爸爸上,那么将子 View和布局参数一起加入到爸爸的孩子当中
【5】如果爸爸是空的或者不需要进行绑定,那么子View就是我们需要返回的那个View,将其赋值给result

7.返回result

源码阅读笔记暂存,之后会将其写成博客。

你可能感兴趣的:(View的绘制流程——第二篇)