从上图能够看到 inflate 方法有四个重载方法,有两个方法第一个参数接收的是一个布局文件id,另外两个接收的是XmlPullParse,看源码就知道,接收布局文件的inflate方法里面调用的是接收XmlPullParse的方法。 bash
所以咱们只须要分析一下三个参数的inflate方法,看一下这个方法的定义:ide
/**
* Inflate a new view hierarchy from the specified xml resource. Throws
* {@link InflateException} if there is an error.
*
* @param resource ID for an XML layout resource to load (e.g.,
* <code>R.layout.main_page</code>)
* @param root Optional view to be the parent of the generated hierarchy (if
* <em>attachToRoot</em> is true), or else simply an object that
* provides a set of LayoutParams values for root of the returned
* hierarchy (if <em>attachToRoot</em> is false.)
* @param attachToRoot Whether the inflated hierarchy should be attached to
* the root parameter? If false, root is only used to create the
* correct subclass of LayoutParams for the root view in the XML.
* @return The root View of the inflated hierarchy. If root was supplied and
* attachToRoot is true, this is root; otherwise it is the root of
* the inflated XML file.
*/
public View inflate(@LayoutRes int resource, @Nullable ViewGroup root, boolean attachToRoot)
复制代码
解释:从指定的xml资源文件加载一个新的View,若是发生错误会抛出InflateException异常。 参数解释: resource:加载的布局文件资源id,如:R.layout.main_page。 root:若是attachToRoot(也就是第三个参数)为true, 那么root就是为新加载的View指定的父View。不然,root只是一个为返回View层级的根布局提供LayoutParams值的简单对象。 attachToRoot: 新加载的布局是否添加到root,若是为false,root参数仅仅用于为xml根布局建立正确的LayoutParams子类(列如:根布局为LinearLayout,则用LinearLayout.LayoutParam)。源码分析
了解了这几个参数的意义后,咱们来看一下前面提到的两种写法 #####第一种:root 为null布局
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.inflate_test_item,null)
复制代码
这多是咱们用得比较多的一种方式,直接提供一个布局,返回一个View,根据上面的几个参数解释就知道,这种方式,没有指定新加载的View添加到哪一个父容器,也没有root提供LayoutParams布局信息。这个时候,若是调用view.getLayoutParams() 返回的值为null。经过上面的测试,咱们知道这种方式会致使RecyclerView Item 布局宽高失效。具体缘由稍后再分析。 #####第二种:root不为null,attachToRoot为false测试
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.inflate_test_item,parent,false)
复制代码
这种方式加载,root不为null,可是attachToRoot 为 false,所以,加载的View不会添加到root,可是会用root生成的LayoutParams信息。 ###源码分析ui
....
//前面省略
//result是最终返回的View
View result = root;
try {
...
// 省略部分代码
final String name = parser.getName();
if (DEBUG) {
System.out.println("**************************");
System.out.println("Creating root view: "
+ name);
System.out.println("**************************");
}
if (TAG_MERGE.equals(name)) {
if (root == null || !attachToRoot) {
throw new InflateException("<merge /> can be used only with a valid "
+ "ViewGroup root and attachToRoot=true");
}
rInflate(parser, root, inflaterContext, attrs, false);
} else {
// 重点就在这个else代码块里了
//解释1:首先建立了xml布局文件的根View,temp View
final View temp = createViewFromTag(root, name, inflaterContext, attrs);
ViewGroup.LayoutParams params = null;
// 解释2:判断root是否为null,不为null,就经过root生成LayoutParams
if (root != null) {
if (DEBUG) {
System.out.println("Creating params from root: " +
root);
}
// Create layout params that match root, if supplied
params = root.generateLayoutParams(attrs);
// 解释3:若是在root不为null, 而且attachToRoot为false,就为temp View(也就是经过inflate加载的根View)设置LayoutParams.
if (!attachToRoot) {
// Set the layout params for temp if we are not
// attaching. (If we are, we use addView, below)
temp.setLayoutParams(params);
}
}
if (DEBUG) {
System.out.println("-----> start inflating children");
}
//解释4:加载根布局temp View 下面的子View
rInflateChildren(parser, temp, attrs, true);
if (DEBUG) {
System.out.println("-----> done inflating children");
}
//解释5: 注意这一步,root不为null ,而且attachToRoot 为true时,才将从xml加载的View添加到root.
if (root != null && attachToRoot) {
root.addView(temp, params);
}
// 解释6:最后,若是root为null,或者attachToRoot为false,那么最终inflate返回的值就是从xml加载的View(temp),不然,返回的就是root(temp已添加到root)
if (root == null || !attachToRoot) {
result = temp;
}
}
}
...
//省略部分代码
return result;
}
复制代码
从上面这段代码就能很清楚的说明前面提到的两种加载方式的区别了。this
第一种加载方式 root为 null :源码中的代码在 解释1
和 解释6
直接返回的就是从xml加载的temp View。spa
第二种加载方式 root不为null ,attachToRoot 为false: 源码中在 解释3
和解释5
,为temp 设置了经过root生成的LayoutParams信息,可是没有add 添加到root 。code
参考文章:www.jianshu.com/p/9a6db88b8…cdn