继续浏览精彩内容
慕课网APP
程序员的梦工厂
打开
继续
感谢您的支持,我会继续努力的
赞赏金额会直接到老师账户
将二维码发送给自己后长按识别
微信支付
支付宝支付

Android LayoutInflater inflate() 图示详解

慕标5832272
关注TA
已关注
手记 1263
粉丝 233
获赞 1008

之前在动态加载一个布局时用 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) {
}

参数解释:

  • @param resource 布局文件id (例如R.layout.main_page

  • @param root

    • 如果参数三 attachToRoottrue, 则参数二是作为参数一中布局文件的父控件

    • 如果参数三 attachToRootfalse, 则参数二是作为提供一组 LayoutParams 值的对象

  • @param attachToRoot 指定参数一的布局 View 对象是否要作为 第二个参数控件上作为子控件

返回值:

  • @returnroot 不为空,且第 attachToRoottrue,则返回root作为根布局,否则,返回参数一 view对象的根布局 作为根布局

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

来源于文末 郭神 博客参考

  • 如果rootnullattachToRoot将失去作用,设置任何值都没有意义,加载的布局文件最外层的所有layout属性会失效,由父布局来重新指定.

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

webp

图一.png


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

webp

图二.png


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

  • 如果root不为nullattachToRoot不论是truefalse,加载的布局文件最外层的所有layout属性都有效,唯一的不同是:

    • attachToRoottrue时,会自动调用root.addView(view, params),最后返回root

实例验证

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)。

webp

图三.jpg

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

  • attachToRootfalse时,会返回view,需手动调用root.addView(view, params).

实例验证

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

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

onCreate: parent---->null

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

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

webp

图四.png


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

  • 在不设置attachToRoot参数的情况下,如果root不为nullattachToRoot参数默认为true.

实例验证

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 两个参数 的 inflatepublic View inflate(@LayoutRes int resource, @Nullable ViewGroup root) {    return inflate(resource, root, root != null);

}



作者:_龙衣
链接:https://www.jianshu.com/p/407c3eae7eb8


打开App,阅读手记
0人推荐
发表评论
随时随地看视频慕课网APP