Android开发经验谈Android开发Android开发

Android LayoutInflater inflate()

2018-12-13  本文已影响9人  d74f37143a31

之前在动态加载一个布局时用 View.inflate() 去加载,最后没加载出来,换为 LayoutInflater.from(mContext).inflate() 之后加载成功。具体场景我没记清了,但是我们可以通过了解这两个方式加载布局的方法来规避以后 使用可能出现的问题。

既然是由 LayoutInflater.from(mContext).inflate() 引出的问题那就从怎么使用开始去一步一步深挖。

LayoutInflater.from(this).inflate()

有 4 个构造方法,前面三个构造方法最终都会调用最后一个构造方法 inflate(XmlPullParser parser, @Nullable ViewGroup root, boolean attachToRoot) 进行布局的解析。

它的四个构造方法如下:


第一个构造方法

public View inflate(@LayoutRes int resource, @Nullable ViewGroup root) {

    return inflate(resource, root, root != null);

}

第二个构造方法

public View inflate(@LayoutRes int resource, @Nullable ViewGroup root, boolean attachToRoot) {
 // 真正实现的过程太长,这里就不贴代码了,可自行去查看源码
}

第三个构造方法

public View inflate(XmlPullParser parser, @Nullable ViewGroup root) {

    return inflate(parser, root, root != null);

}

第四个构造方法

public View inflate(XmlPullParser parser, @Nullable ViewGroup root, 
                boolean attachToRoot) {
    // 真正实现的过程太长,这里就不贴代码了,可自行去查看源码
}

我们常用的是第一个构造方法,但是第一个构造方法会调用第二个构造函数,所以我们 直接分析第二个构造方法。

它的构造方法参数介绍如下所示:

public View inflate(@LayoutRes int resource, @Nullable ViewGroup root, 
                  boolean attachToRoot) {
}

参数解释:

返回值:

LayoutInflater.from(mContext).inflate() 小结

来源于文末 郭神 博客参考

实例验证
图一是rootnullattachToRoot=true 修改 R.layout.inflate_test_btn 的宽度为300dp的结果,很明显没修改成功。在测试过程中我修改了 attachToRoot=false,结果还是不变。

图一.png

图二是修改了父布局宽度为300dp

图二.png

验证结果正确:由父布局指定。

实例验证

resourceR.layout.inflate_test_btnattachToRoottrue, rootcontentLayout ,完整调用如:LayoutInflater.from(this).inflate(R.layout.inflate_test_btn, contentLayout, true);

这时候如果不处理,会崩溃:

The specified child already has a parent. 
You must call removeView() on the child's parent first.

通过打印 parent 得到如下信息:

onCreate: parent---->android.widget.LinearLayout{
4016a11 V.E...... ......I. 0,0-0,0 #7f0d007e app:id/root_layout}

原来还可以这样查看父布局。。
根据提示我们只能先移除其它子view 再添加

结合图三以及崩溃日志,可以证明会自动调用 root.addView(view, params)。

图三.jpg

验证结果正确:会自动调用 root.addView(view, params),最后返回 root。

实例验证

resourceR.layout.inflate_test_btnattachToRootfalse, rootcontentLayout ,完整调用如:LayoutInflater.from(this).inflate(R.layout.inflate_test_btn, contentLayout, false);

通过打印 parent 得到如下信息:

onCreate: parent---->null

        不会崩溃,可以正常添加, 而且父布局中的子 view 都存在

图四可以证明 root.addView()是需要手动添加的.

图四.png

验证结果:需手动调用 root.addView(view, params)

实例验证

resourceR.layout.inflate_test_btnattachToRoot不设置或者是设置为false, rootcontentLayout ,完整调用如:
LayoutInflater.from(this).inflate(R.layout.inflate_test_btn, contentLayout, false);
LayoutInflater.from(this).inflate(R.layout.inflate_test_btn, contentLayout,);

LayoutInflater.from(this).inflate(R.layout.inflate_test_btn,contentLayout);

        会崩溃

LayoutInflater.from(this).inflate(R.layout.inflate_test_btn,contentLayout,false);

        不会崩溃

验证结果正确:如果 root 不为 null, attachToRoot 参数默认为 true.

关于 View 类的 inflate 方法

View.inflate是对 LayoutInflater inflate 的进一步封装,但是只实现了 LayoutInflater inflate 两个参数的构造方法,所以功能相对 LayoutInflater会弱一些。我们可以通过源码直接看出二者的关系。

View.inflate实现的源码如下:

参数介绍:
context 表示上下文
resource 表示要填充的 `xml` 文件
root 填充成的 `view` 对象的根布局

public static View inflate(Context context, @LayoutRes int resource, ViewGroup root) {

    LayoutInflater factory = LayoutInflater.from(context);

    return factory.inflate(resource, root);

}

构造方法中调用 LayoutInflater.from(this).inflate 两个参数 的 inflate

public View inflate(@LayoutRes int resource, @Nullable ViewGroup root) {

    return inflate(resource, root, root != null);

}

参考

Android LayoutInflater原理分析,带你一步步深入了解View(一)

上一篇 下一篇

猜你喜欢

热点阅读