LayoutInflater两个inflate方法的区别
2016-04-06 18:09
197 查看
LayoutInflater类中有多个inflate方法,这里简要说一下:
这两个方法的区别,以及第二个方法中boolean变量的作用。
以前在使用ListView,Adapter的getView方法中,经常使用第一个方法来加载布局文件:
这时IDE会弹出warning:
Avoid passing null as the view root (needed to resolve layout parameters on the inflated layout’s root element)
提示我们不要传递”null”作为root的参数,因为需要决定root节点的属性。
在这里,可以换用另一个inflate方法来避免这个warning:
使用三个参数的inflate方法,设定root参数为getView中的parent参数,设定attachToRoot为false。
这几个参数有何意义呢?我们来看一下两个inflate方法的实现。
首先两个参数的inflate方法是这样定义的:
root参数根据标注,是可以为null的。在函数内部,实际是调用了三个参数的inflate方法。
如果我们设定root不为空,实际等于:
若我们给定root为null,则实际是在调用:
那接下来就来看一下三个参数的inflate方法的内部实现:
在这里通过给定的layout资源(R.layout.*)生成了XmlResourceParser变量,并调用另一个inflate方法,因此关键步骤就在接收XmlResourceParser参数的inflate方法中了,我们来看他的内部实现,代码很多,仅保留关键步骤:
简要来说:
1. 两个参数的inflate方法实际是在内部再调用三个参数的inflate方法
2. root为null,则最终要返回xml中最外层view
3. root不为null,若不需要attach,则还是返回xml中最外层view
4. root不为null,且需要attach,则通过root的addview方法,将xml整体添加到root中。如果xml最外层是merge标签,则直接在root下加载xml中的子节点。最终返回root整体这一view。
*若给定的root为null,那么就无法将root的LayoutParams设定给xml中的父view了。
public View inflate(int resource, ViewGroup root) public View inflate(int resource, ViewGroup root, boolean attachToRoot)
这两个方法的区别,以及第二个方法中boolean变量的作用。
以前在使用ListView,Adapter的getView方法中,经常使用第一个方法来加载布局文件:
@Override public View getView(int position, View convertView, ViewGroup parent) { if (convertView == null) { convertView = layoutInflater.inflate(R.layout.list_item, null); } }
这时IDE会弹出warning:
Avoid passing null as the view root (needed to resolve layout parameters on the inflated layout’s root element)
提示我们不要传递”null”作为root的参数,因为需要决定root节点的属性。
在这里,可以换用另一个inflate方法来避免这个warning:
@Override public View getView(int position, View convertView, ViewGroup parent) { if (convertView == null) { // 使用三个参数的inflate方法,设定root参数为getView中的parent参数,设定attachToRoot为false convertView = layoutInflater.inflate(R.layout.list_item, parent, false); } }
使用三个参数的inflate方法,设定root参数为getView中的parent参数,设定attachToRoot为false。
这几个参数有何意义呢?我们来看一下两个inflate方法的实现。
首先两个参数的inflate方法是这样定义的:
public View inflate(@LayoutRes int resource, @Nullable ViewGroup root) { return inflate(resource, root, root != null); }
root参数根据标注,是可以为null的。在函数内部,实际是调用了三个参数的inflate方法。
如果我们设定root不为空,实际等于:
layoutInflater.inflate(R.layout.list_item, parent, true);
若我们给定root为null,则实际是在调用:
layoutInflater.inflate(R.layout.list_item, null, false);
那接下来就来看一下三个参数的inflate方法的内部实现:
public View inflate(@LayoutRes int resource, @Nullable ViewGroup root, boolean attachToRoot) { final Resources res = getContext().getResources(); if (DEBUG) { Log.d(TAG, "INFLATING from resource: \"" + res.getResourceName(resource) + "\" (" + Integer.toHexString(resource) + ")"); } final XmlResourceParser parser = res.getLayout(resource); try { return inflate(parser, root, attachToRoot); } finally { parser.close(); } }
在这里通过给定的layout资源(R.layout.*)生成了XmlResourceParser变量,并调用另一个inflate方法,因此关键步骤就在接收XmlResourceParser参数的inflate方法中了,我们来看他的内部实现,代码很多,仅保留关键步骤:
public View inflate(XmlPullParser parser, @Nullable ViewGroup root, boolean attachToRoot) { synchronized (mConstructorArgs) { // 设定return的View(result)为参数root,后面以paramRoot代替 View result = root; try { // 查找xml文件中的root节点,后面以xmlRoot代替 int type; while ((type = parser.next()) != XmlPullParser.START_TAG && type != XmlPullParser.END_DOCUMENT) { // Empty } // 若没有开始节点,抛出异常(搜寻xmlRoot失败) if (type != XmlPullParser.START_TAG) { throw new InflateException(parser.getPositionDescription() + ": No start tag found!"); } final String name = parser.getName(); if (TAG_MERGE.equals(name)) { // 若xml头节点为merge,判断是否需要attch到paramRoot // paramRoot为null,或不需要attach到paramRoot(我们传入了null参数),抛出异常,merge标签必须要有有效的root节点 if (root == null || !attachToRoot) { throw new InflateException("<merge /> can be used only with a valid " + "ViewGroup root and attachToRoot=true"); } // paramRoot有效,在其下载入xml子节点,然后直接到函数结束return处 rInflate(parser, root, inflaterContext, attrs, false); } else { // xml头节点非merge,通过函数获取到xmlRoot节点 final View temp = createViewFromTag(root, name, inflaterContext, attrs); ViewGroup.LayoutParams params = null; // paramRoot不为null,来获取其param属性 if (root != null) { params = root.generateLayoutParams(attrs); // 如果不attach到paramRoot,则将paramRoot的param设定到xmlRoot中 if (!attachToRoot) { temp.setLayoutParams(params); } } // 在temp下载入xmlRoot的子节点 rInflateChildren(parser, temp, attrs, true); // 如果paramRoot不为null,并且我们设定需要attach,则使用addView,将temp添加到root中 if (root != null && attachToRoot) { root.addView(temp, params); } // 如果root为null,或者我们设定不需要attach,则直接返回xmlRoot即可; // 否则需要返回paramRoot,我们在函数一开始已经默认设置了 if (root == null || !attachToRoot) { result = temp; } } } catch (XmlPullParserException e) { } catch (Exception e) { } finally { } // 返回加载完的View return result; } }
简要来说:
1. 两个参数的inflate方法实际是在内部再调用三个参数的inflate方法
2. root为null,则最终要返回xml中最外层view
3. root不为null,若不需要attach,则还是返回xml中最外层view
4. root不为null,且需要attach,则通过root的addview方法,将xml整体添加到root中。如果xml最外层是merge标签,则直接在root下加载xml中的子节点。最终返回root整体这一view。
*若给定的root为null,那么就无法将root的LayoutParams设定给xml中的父view了。
相关文章推荐
- 笔试练习三
- java.io.FileNotFoundException: URL [jndi:/localhost/myBlogSys/WEB-INF/classes/] cannot be resolved t
- mongoDB window平台安装MongoDB
- VI nagios
- [MUI框架]-滑动侧边栏-webview模式
- TextView+ScrollView显示大量文本(小说)
- 基于Http协议的Android网络编程
- OPRNGL之渲染过程大概梳理
- php 使用GD库压缩图片,添加文字图片水印
- 串口初始化
- /proc/sysrq-trigger文件的功能
- Android酷炫实用的开源框架(UI框架)
- webservice开发
- GDB 反向调试(Reverse Debugging)
- 问题1:javascript的函数对象问题
- mybatis generator maven-plugin 集成
- numpy 学习,里面有converters参数的使用方法
- IP格式合法问题研究
- mysql两大存储引擎的区别与选择
- Qt Quick实现的涂鸦程序