美文网首页
关于View.inflate(Context, int, Vie

关于View.inflate(Context, int, Vie

作者: 咸鱼Jay | 来源:发表于2017-08-07 11:33 被阅读24次

当我们在自定义布局或者在RecyclerView的onBindViewHolder方法中使用下面的方法进行布局加载
View view = View.inflate(parent.getContext(), R.layout.item_layout, null);
但是上面的方法中ViewGroup的参数到底是传值呢,还是不传呢?
并且和View view= LayoutInflater.from(context).inflate(R.layout.item_layout, parent, false);这个又有啥区别呢?
现在我们进行源码分析

  1. 进入View的inflate方法
public static View inflate(Context context, @LayoutRes int resource, ViewGroup root) {
        LayoutInflater factory = LayoutInflater.from(context);
        return factory.inflate(resource, root);
}

发现原来最终是使用LayoutInflater.from(context).inflate(resource, root);来调用的inflate方法

2.继续进入是LayoutInflater类的inflate方法,如下:

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

这里又是调用的是inflate(resource,root,root!= null);虽然前面没有attachToRoot这个参数,但是在这里有调用了带attachToRoot这个参数的方法,并且根据root的是否为null传入该参数。
3.继续进入inflate方法

public View inflate(@LayoutRes int resource, @Nullable ViewGroup root, boolean attachToRoot) {
        final Resources res = getContext().getResources();
        if (DEBUG) {
            Log.d(TAG, "INFLATING from resource: \"" + res.getResourceName(resource) + "\" ("
                    + Integer.toHexString(resource) + ")");
        }

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

到这里才是才是所有的方法的入口,这个方法中主要是把传入的布局进行解析

4.进入inflate(parser,root,attachToRoot);方法,这个方法中主要做了

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

                View result = root;

                ....

                if (TAG_MERGE.equals(name)) {
                    ....
                } else {
                    // Temp is the root view that was found in the xml
                    final View temp = createViewFromTag(root, name, inflaterContext, attrs);

                    ViewGroup.LayoutParams params = null;

                    if (root != null) {
                        // 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)
                            temp.setLayoutParams(params);
                        }
                    }

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

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

                    // Decide whether to return the root that was passed in or the
                    // top view found in xml.
                    if (root == null || !attachToRoot) {
                        result = temp;
                    }
                }
          .....
            return result;
        }
    }

进行分析,View result = root,且ViewGroup的LayoutParams首先会被设置为null,
①当root为null或者attachToRoot为false时,ViewGroup的LayoutParams会为null,并将temp赋值给result进行返回。
②当root不为null时,params才会被赋值,同时attachToRoot为false时才会把params设置给temp,temp是啥?就是根据inflate传递的参数生成的view。
③当root不为null时,同时attachToRoot为true时,会调用root.addView(temp, params);这里也就是当我们在RecyclerView的onCreateViewHolder方法中使用View inflate = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_layout, parent, true);时会报下面这个错:
java.lang.IllegalStateException: The specified child already has a parent. You must call removeView() on the child's parent first.

相关文章

网友评论

      本文标题:关于View.inflate(Context, int, Vie

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