View.inflate和LayoutInflater.inflate方法区别及源码

        View.inflate和LayoutInflater.inflate都是我们平时常用的方法,一直来回用也没有注意两者的区别,做一个列表让条目加上颜色的功能,使用View.inflate总是不能实现,于是找了下源码。

我们首先看一看View.inflate的调用:

public static View inflate(Context context, @LayoutRes int resource, ViewGroup root) {
        LayoutInflater factory = LayoutInflater.from(context);
        return factory.inflate(resource, root);
    }
  public View inflate(@LayoutRes int resource, @Nullable ViewGroup root){
        /**
        请仔细看这个位置,root != null,也就是说当我们在View.inflate中第三个参数
        给的是null,那么attachToRoot就已经指定了false
        */
        return inflate(resource, root, root != null);
    }

下面是核心的部分:

             
            if (root != null) {
                        if (DEBUG) {
                            System.out.println("Creating params from root: " +
                                    root);
                        }
                        // Create layout params that match root, if supplied
                        params = root.generateLayoutParams(attrs);
                        if (!attachToRoot) {
                            // Set the layout params for temp if we are not
                            // attaching. (If we are, we use addView, below)
                            //只有当root不为空并且attachToRoot不为空时temp才会有赋值
                            temp.setLayoutParams(params);
                        }
                    }

                    if (DEBUG) {
                        System.out.println("-----> start inflating children");
                    }

                    // Inflate all children under temp against its context.
                    rInflateChildren(parser, temp, attrs, true);

                    if (DEBUG) {
                        System.out.println("-----> done inflating children");
                    }

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

从上面我们能看出,只有当root以及attachToRoot不为空时,temp会设置layoutParams,也就是说如果需要对列表的条目的父控件做处理,那么root我们必须设置不为空,但是列表中,我们不能给View.inflate设置root,因为无论使用listview还是recycleView,调用getVIew的时候就已经设置过父布局了,如果这个时候我们传入root,会报出 The specified child already has a parent. " "You must call removeView() on the child's parent first

所以解决方法:

1 使用LayoutInflater.from(viewGroup.getContext()).inflate(android.R.layout.aaa, viewGroup,false));

2 给你的布局多套用一层,你不是说最外层的设置不起作用了吗,只能绘制加进去的view,那么我就把我原来的父控件外面再套一层,使用的时候设置父控件下面一级的布局,当然这个会造成布局的过度重绘,不建议。

你可能感兴趣的:(View.inflate和LayoutInflater.inflate方法区别及源码)