android 自定义view 获取为null,是Android的自定义View-进阶知识-inflate方法的解惑

前言

在自定义View中其实还有一个十分常见的类是我们经常会使用到的那就是LayoutInflater。为什么会说它常用呢?还记得之前的文章有讲过,自定义View有一种实现方式是通过多个已有控件进行组合来实现的,那么这就需要通过LayoutInflater的inflate方法对定义好的xml文件进行转译,对,没错,是转译,前文中提到的这个方法其原理就是对xml文件进行读取,进而转化为实际的布局。

关于LayoutInflater的inflate方法其实用一直在用,也都知道它最终是用来获取View对象的,但是这个方法最让人搞不清楚的是它的参数,所以本文主要的内容是来讲解一下其参数的具体含义。

方法分析

一般的,我们是这样使用LayoutInflater的inflate方法的:

val view = LayoutInflater.from(context).inflate(R.layout.view_custom, this)

通过如上的方法,我们就可以获取到我们所需要布局的View对象,那么我们进入到这个方法中去:

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

final Resources res = getContext().getResources();

View view = tryInflatePrecompiled(resource, res, root, attachToRoot);

if (view != null) {

return view;

}

XmlResourceParser parser = res.getLayout(resource);

try {

return inflate(parser, root, attachToRoot);

} finally {

parser.close();

}

}

这个方法所做的是将xml资源文件转化为一个Xml的解析器进而去进行下一步操作,此外这里二参方法还有另外一个重载方法:

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

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

}

其指向的也是接下来这个三参方法,说明方法调用到最后都会来到下面这个方法来执行核心逻辑:

在分析前,我们要明确我们分析的目的是理解方法参数的含义,从方法的调用顺序来看,主要关注的是root和attachToRoot这两个参数。

// 省略了安全判断和部分无用代码

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

synchronized (mConstructorArgs) {

final Context inflaterContext = mContext;

final AttributeSet attrs = Xml.asAttributeSet(parser);

Context lastContext = (Context) mConstructorArgs[0];

mConstructorArgs[0] = inflaterContext;

View result = root;

try {

advanceToRootNode(parser);

final String name = parser.getName();

···

// 获取当前根视图

final View temp = createViewFromTag(root, name, inflaterContext, attrs);

ViewGroup.LayoutParams params = null;

// root != null

if (root != null) {

// 如果attachToRoot为false的话只会对当前布局设置其父布局的相关属性配置,但并不会将View add到父布局上

params = root.generateLayoutParams(attrs);

if (!attachToRoot) {

temp.setLayoutParams(params);

}

}

// root != null 同时attachToRoot为true,会在应用布局配置的同时将View添加到父布局上去

if (root != null && attachToRoot) {

root.addView(temp, params);

}

// root == null 不做任何操作,直接返回了创建好的View

if (root == null || !attachToRoot) {

result = temp;

}

}

return result;

}

}

简单地对方法地调用做了分析,其中源码具体实现没有展开,只追了我们关注那部分逻辑,下面根据追源码地结果来进行一下总结:

root为null时,attachToRoot值失去作用,会返回一个View对象,但是不会有任何的操作,也不会依附于某个ViewGroup进行展示

root不为null,attachToRoot为true,会将View加载到指定的父布局上,即root上

root不为null,attachToRoot为false,view最外层的layout相关属性会配置,但是view不会加载到任何布局上,只用手动add后layout相关属性才会生效

以上就是关于inflate这个方法相关的解惑,重点分析了不同参数所最终实现的效果是怎么样的,一般的情况直接使用二参方法去获取View对象就可以啦,其它的根据实际场景去针对性的选择使用。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值