动态加载布局LayoutInflater.inflate()源代码解析

来源:互联网 发布:plc编程梯形图简单实例 编辑:程序博客网 时间:2024/06/06 03:46

动态加载布局LayoutInflater.inflate()源代码解析

如何获取LayoutInflater

获得 LayoutInflater 实例的三种方式

1.LayoutInflater inflater = getLayoutInflater(); //调用Activity的getLayoutInflater()

2.LayoutInflater localinflater =(LayoutInflater)context.getSystemService

                                            (Context.LAYOUT_INFLATER_SERVICE);
  1. LayoutInflater inflater = LayoutInflater.from(context);

本质上都是调用方式二。

LayoutInflater.inflate()源代码分析

1.两个参数的inflate方法。

 /**     * Inflate a new view hierarchy from the specified xml resource. Throws     * {@link InflateException} if there is an error.     *      * @param resource ID for an XML layout resource to load (e.g.,     *        <code>R.layout.main_page</code>)     * @param root Optional view to be the parent of the generated hierarchy.     * @return The root View of the inflated hierarchy. If root was supplied,     *         this is the root View; otherwise it is the root of the inflated     *         XML file.     */    public View inflate(@LayoutRes int resource, @Nullable ViewGroup root) {        return inflate(resource, root, root != null);    }

第一个参数是加载的xml布局资源,第二个是父布局。里面会调用三个参数的方法。

2.看一下三个参数的方法

/**     * Inflate a new view hierarchy from the specified xml resource. Throws     * {@link InflateException} if there is an error.     *      * @param resource ID for an XML layout resource to load (e.g.,     *        <code>R.layout.main_page</code>)     * @param root Optional view to be the parent of the generated hierarchy (if     *        <em>attachToRoot</em> is true), or else simply an object that     *        provides a set of LayoutParams values for root of the returned     *        hierarchy (if <em>attachToRoot</em> is false.)     * @param attachToRoot Whether the inflated hierarchy should be attached to     *        the root parameter? If false, root is only used to create the     *        correct subclass of LayoutParams for the root view in the XML.     * @return The root View of the inflated hierarchy. If root was supplied and     *         attachToRoot is true, this is root; otherwise it is the root of     *         the inflated XML file.     */    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();        }    }

最终会调用,inflate(parser, root, attachToRoot);方法。
第三个参数attachToRoot是true的时候,会自动加载到第二个参数提到的父布局。

3.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 result = root;            try {                // Look for the root node.                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                    final View temp = createViewFromTag(root, name, inflaterContext, attrs);                    ViewGroup.LayoutParams params = 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)                            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);                    }                    // Decide whether to return the root that was passed in or the                    // top view found in xml.                    if (root == null || !attachToRoot) {                        result = temp;                    }                }            } catch (XmlPullParserException e) {                InflateException ex = new InflateException(e.getMessage());                ex.initCause(e);                throw ex;            } catch (Exception e) {                InflateException ex = new InflateException(                        parser.getPositionDescription()                                + ": " + e.getMessage());                ex.initCause(e);                throw ex;            } finally {                // Don't retain static reference on context.                mConstructorArgs[0] = lastContext;                mConstructorArgs[1] = null;            }            Trace.traceEnd(Trace.TRACE_TAG_VIEW);            return result;        }    }

4.总结分析

<1当调用两个参数的时候inflate()

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

如果父布局不为空,那么会默认inflate(XmlPullParser parser, @Nullable ViewGroup root, boolean attachToRoot)第三个参数也是true。

第三个参数的作用如下;

if (root != null && attachToRoot) {                        root.addView(temp, params);                    }

第三个参数是空的时候,会自动添加到第二个参数的父布局中。

<2 第二个参数的作用

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)                            temp.setLayoutParams(params);                        }                    }

当只有第二个参数不为空时候,view的layoutparam才有意义,否则是就是空,那么在xml在设置的高宽,margin就没有意义了,会使用默认的layoutparam,默认的layoutparam的的layout;width和layout:height都是wrap_content。

5.inflate的重载方式

如下四种:

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

最终都会调用 inflate(XmlPullParser parser, @Nullable ViewGroup root, boolean attachToRoot)方法。

原创粉丝点击