好久没有写博客了,=_=…可能工作了,时间确实有点紧张….

我们常用的布局的加载的方法有两种:

View.inflate(context,resId,root);
            LayoutInflater.inflate(context,resId,root);

那么这两种之间有什么关系呢?
通过底层的源码来说,其实都是通过LayoutInflate来加载布局的;

那么这两个加载的方式有什么不同吗?
如果我们简单的查看一下源码的话,会发现一个问题就是=_=,View.inflate的实现就是LayoutInflate的inflate方法的实现,源码如下:

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

但是这里继续深究:LayoutInflate.inflate(resource,root);

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

这个方法inflate(Resource,root)的实现,其实是LayoutInflate的另一个方法:inflate(resourse,root,root!=null)来完成的,我们继续向下看:

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

我们会发现上面的那个方法是其实是一个public访问的;

这里的话,我们整理一下思路,到目前位置,大概的顺序是这样的:

SmartRefreshLayout加载更多布局_博客

我们注意一点如下:
- View.inflate()传入的root,如果是空的话,在LayoutInflate中的View inflate(@LayoutRes int resource, @Nullable ViewGroup root, boolean attachToRoot)方法中的attachToRoot就为false;

接着我们继续看对布局真正加载的方法: inflate(parser, root, attachToRoot);

public View inflate(XmlPullParser parser, @Nullable ViewGroup root, boolean attachToRoot) {
    synchronized (mConstructorArgs) {
        Trace.traceBegin(Trace.TRACE_TAG_VIEW, "inflate");

        final Context inflaterContext = mContext;
        final AttributeSet attrs = Xml.asAttributeSet(parser);
        Context lastContext = (Context) mConstructorArgs[0];
        mConstructorArgs[0] = inflaterContext;
        //这里是View.inflate()的最后一个参数,root
        View result = root;

        try {
            // Look for the root node.
            //对xml进行的一个解析操作;
            int type;
            while ((type = parser.next()) != XmlPullParser.START_TAG &&
                    type != XmlPullParser.END_DOCUMENT) {
                // Empty
            }

            if (type != XmlPullParser.START_TAG) {
                throw new InflateException(parser.getPositionDescription()
                        + ": No start tag found!");
            }

            final String name = parser.getName();

            if (DEBUG) {
                System.out.println("**************************");
                System.out.println("Creating root view: "
                        + name);
                System.out.println("**************************");
            }

            if (TAG_MERGE.equals(name)) {
                if (root == null || !attachToRoot) {
                    throw new InflateException("<merge /> can be used only with a valid "
                            + "ViewGroup root and attachToRoot=true");
                }

                rInflate(parser, root, inflaterContext, attrs, false);
            } else {
                // Temp is the root view that was found in the xml
                //这里是将布局真正的进行一个加载成一个View对象,但是这个view对象没有LayoutParams属性;
                final View temp = createViewFromTag(root, name, inflaterContext, attrs);

                ViewGroup.LayoutParams params = null;

                if (root != null) {

                    // Create layout params that match root, if supplied
                    //根据root提供的上下文环境,对加载的xml属性进行一个读取;
                    params = root.generateLayoutParams(attrs);
                    if (!attachToRoot) {
                    //这里表示root不为空,attach为false,这个时候将上面加载出来的布局设置加载好的LayoutParmas
                        // Set the layout params for temp if we are not
                        // attaching. (If we are, we use addView, below)
                        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.
                //这里表示,如果root,不为null,且,attachToRoot为true;
                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.
                //root为null的时候,将result=temp,初始化的时候,result=root的
                if (root == null || !attachToRoot) {
                    result = temp;
                }
            }  
        }

        return result;
    }
}

从上面的代码我们可以知道如下:
1、 我们使用View.Inflate()加载出来的布局,如果传入了root,
- 这个加载的xml文件中的属性,会根据root提供的上下文环境进行一个生效

-将传入的xml加载出来的对象直接添加到了root中;

-这方法的返回值为root

如果没有root的话,xml文件的跟布局的layout属性是不会生效的,是包裹内容的大小,此时方法的返回值是加载出来的view;

2、如果我们使用LayoutInflate的 View inflate(@LayoutRes int resource, @Nullable ViewGroup root, boolean attachToRoot)方法来加载布局的时候:

-传入的root,并且attachToRoot为true,和View.inflate加载的效果一样;

-传入root为空和View.inflate的效果一样;

-传入root,并且attachToRoot为false,加载出来的View,不会被添加到root中,但是xml加载出来的View的layout属性的是会根据root提供的环境被设置到加载出来的View中,此时返回的View是xml加载出来的view;