LayoutInflater.inflater()方法及参数源码分析

LayoutInflater.inflater()方法及参数源码分析

  

  inflate加载布局的时候有四个方法提供,分别如下


  平常主要用到的还是前两个。

  下面从源码角度分析一下这四个方法的区别和用法。

1、方法1

public View inflate(@LayoutResint resource, @Nullable ViewGroup root) {
    return inflate(resource, root, root != null);
}

resource:需要加载布局文件的id,意思是需要将这个布局文件中加载到Activity中来操作。

root:需要附加到resource资源文件的根控件,什么意思呢,就是inflate()会返回一个View对象,如果第三个参数attachToRoot

      为true,就将这个root作为根对象返回,否则仅仅将这个root对象的LayoutParams属性附加到resource对象的根布局对象

      上(方法4的红色背景代码区域就是LayoutPara马上参数),也就是布局文件resource的最外层的View上。

 

2、方法2

public View inflate(@LayoutResint resource, @Nullable ViewGroup root, boolean attachToRoot) {

final Resources res =getContext().getResources();
if (DEBUG) {
    Log.d(TAG, "INFLATINGfrom resource: \"" + res.getResourceName(resource) + "\"("
            + Integer.toHexString(resource)+ ")");
}

final XmlResourceParserparser = res.getLayout(resource);
try {
    return inflate(parser, root, attachToRoot);
} finally {
    parser.close();
}

}

attachToRoot:是否将root附加到布局文件的根视图上。

如果没有传递attachToRoot参数,则根据root是否为null判断。

 

3、方法3

public View inflate(XmlPullParserparser, @Nullable ViewGroup root) {
    return inflate(parser, root, root != null);
}


4、方法4

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

……

if (root != null) {
    if (DEBUG) {
        System.out.println("Creatingparams from root: " +
                root);
    }
    // Create layout params that matchroot, if supplied
    params =root.generateLayoutParams(attrs);
    if (!attachToRoot) {
        // Set the layout params for temp if we arenot
        // attaching. (If we are, we useaddView, below)
        temp.setLayoutParams(params);
    }
}

 

…….

 

// We are supposedto attach all the views we found (int temp)
// to root. Do that now.
if (root != null && attachToRoot) {
    root.addView(temp, params);
}

 

 

}

 

  从4个方法的源码可以看出,方法1实际调用的是方法2,方法2和方法3实际调用的都是方法4。也就是方法4是最终被调用的。

  方法4中有个参数params,是根据root!=null条件下实例化的,如果root传递的是null,那么params就为空。在适配器中使用View.inflate(Context context,int resource, ViewGroup root)实例化布局文件时,经常出现的一个NullPointException—LayoutParams为空error就是这个问题引起的,下面详细说一下。

 

  View.inflate(Contextcontext,int resource, ViewGroup root)实例化布局文件时,当root为null时引起的LayoutParams为null异常问题 和root不为null时引起的The specified child already has a parent.You must call removeView() onthe child’s parent first问题。

查看inflate源码如下:

public static View inflate(Contextcontext, @LayoutRes int resource, ViewGroup root) {
    LayoutInflater factory =LayoutInflater.from(context);
    return factory.inflate(resource, root);
}

实质是调用的上面的方法1。

此处我们来分别看下View.inflate(this,resource,root);和View.inflate(this,resource,null);root为空和不为空都会引起错误原因

(1). View.inflate(this,resource,null);root为null时,根据源码流程—>调用方法1.inflate(resource, null);—>方法2 inflate(resource, null, false); -à方法4 inflate(parser, null, false); 查看方法4中红色背景区域代码,判断条件是root!=null,,而此时root==null,,所以就会报出LayoutParams为null的错误。

(2). View.inflate(this,resource,root);root不为null时,根据源码流程—>调用方法1.inflate(resource, root);—>方法2 inflate(resource, root,true); -à方法4 inflate(parser,root,true); 查看方法4中灰色背景区域代码,判断条件是if (root != null &&attachToRoot) ,,判断条件为true,。执行root.addView(temp,params); 把布局和布局参数添加到了根布局,此时就会报出The specified childalready has a parent.You must call removeView() on the child’s parent first问题。

      为什么会重复加载呢,因为RecyclerView/ListView会自动将child添加到它的布局里面去,这里attachToRoot如果为true,就会出现重复加载的问题。

 

 

   解决这两个问题的方法就是,root不为null,但是要传递attachToRoot参数为false。







评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值