android layoutinflater原理分析,Android LayoutInflater inflate() 图示详解

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

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

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

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

返回值:

@return 若 root 不为空,且第 attachToRoot 为 true,则返回root作为根布局,否则,返回参数一 view对象的根布局 作为根布局

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

来源于文末 郭神 博客参考

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

实例验证

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

87d15f30ebab74e9ead0af1300e776b7.png

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

6ca388d6a6f2b52867074e9497f0c30e.png

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

如果root不为null,attachToRoot不论是true或false,加载的布局文件最外层的所有layout属性都有效,唯一的不同是:

attachToRoot为true时,会自动调用root.addView(view, params),最后返回root;

实例验证

resource为R.layout.inflate_test_btn,attachToRoot为true, root为contentLayout ,完整调用如: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)。

9c2243c0e93325219163d45db40de97d.png

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

attachToRoot为false时,会返回view,需手动调用root.addView(view, params).

实例验证

resource为R.layout.inflate_test_btn,attachToRoot为false, root为contentLayout ,完整调用如:LayoutInflater.from(this).inflate(R.layout.inflate_test_btn, contentLayout, false);

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

onCreate: parent---->null

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

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

02cd0d0c75ed3977efc392e1da14589b.png

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

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

实例验证

resource为R.layout.inflate_test_btn,attachToRoot不设置或者是设置为false, root为contentLayout ,完整调用如:

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

}

参考

本文同步分享在 博客“_龙衣”(CSDN)。

如有侵权,请联系 support@oschina.cn 删除。

本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值