美文网首页
是Android的自定义View-进阶知识-inflate方法的

是Android的自定义View-进阶知识-inflate方法的

作者: redrain39 | 来源:发表于2021-01-11 18:12 被阅读0次

前言

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

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

方法分析

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

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

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

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

// 省略了安全判断和部分无用代码
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对象就可以啦,其它的根据实际场景去针对性的选择使用。

相关文章

网友评论

      本文标题:是Android的自定义View-进阶知识-inflate方法的

      本文链接:https://www.haomeiwen.com/subject/jendaktx.html