LayoutInflater 到底怎么把xml添加到decorview

来源:互联网 发布:各大国家的顶级域名 编辑:程序博客网 时间:2024/06/06 04:11

LayoutInflater 到底怎么把xml添加到decorview


      Actity调用setContentView时初始化decorview后会根据layoutResID加载布局。

  

     下面是源码加载过程:

     PhoneWindow.java:      

 @Override    public void setContentView(int layoutResID) {        // Note: FEATURE_CONTENT_TRANSITIONS may be set in the process of installing the window        // decor, when theme attributes and the like are crystalized. Do not check the feature        // before this happens.        if (mContentParent == null) {            installDecor();        } else if (!hasFeature(FEATURE_CONTENT_TRANSITIONS)) {            mContentParent.removeAllViews();        }        if (hasFeature(FEATURE_CONTENT_TRANSITIONS)) {            final Scene newScene = Scene.getSceneForLayout(mContentParent, layoutResID,                    getContext());            transitionTo(newScene);        } else {            mLayoutInflater.inflate(layoutResID, mContentParent);        }

              LayoutInflater.java:


public View inflate(@LayoutRes int resource, @Nullable ViewGroup root) {        //将布局id和容器id传入       return inflate(resource, 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) + ")");        }           //根据layoutId获取xml解析器         final XmlResourceParser parser = res.getLayout(resource);        try {             //将xml解析器和ViewGroup容器、是否加载到根节点下传入 inflate方法中            return inflate(parser, root, attachToRoot);        } finally {            parser.close();        }    }        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;   //把(contentPerent)ViewGroup赋值给result            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)) {//判断根节点是否为merge标签                    if (root == null || !attachToRoot) {//判断root是否为空,merge必须添加到ViewGroup里                        throw new InflateException("<merge /> can be used only with a valid "                                + "ViewGroup root and attachToRoot=true");                    }                    rInflate(parser, root, inflaterContext, attrs, false);                } else {//当根节点不是merge标签时                    // 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);//调用content的FrameLayout的属性解析                        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;        }    } final void rInflateChildren(XmlPullParser parser, View parent, AttributeSet attrs,            boolean finishInflate) throws XmlPullParserException, IOException {        rInflate(parser, parent, parent.getContext(), attrs, finishInflate);    }    /**     * Recursive method used to descend down the xml hierarchy and instantiate     * views, instantiate their children, and then call onFinishInflate().     * <p>     * <strong>Note:</strong> Default visibility so the BridgeInflater can     * override it.     */    void rInflate(XmlPullParser parser, View parent, Context context,            AttributeSet attrs, boolean finishInflate) throws XmlPullParserException, IOException {        final int depth = parser.getDepth();        int type;        while (((type = parser.next()) != XmlPullParser.END_TAG ||                parser.getDepth() > depth) && type != XmlPullParser.END_DOCUMENT) {            if (type != XmlPullParser.START_TAG) {                continue;            }            final String name = parser.getName();                        if (TAG_REQUEST_FOCUS.equals(name)) {                parseRequestFocus(parser, parent);            } else if (TAG_TAG.equals(name)) {                parseViewTag(parser, parent, attrs);            } else if (TAG_INCLUDE.equals(name)) {//如果标签名为include                if (parser.getDepth() == 0) {                    throw new InflateException("<include /> cannot be the root element");//include 标签不能作为根节点                }                parseInclude(parser, context, parent, attrs);            } else if (TAG_MERGE.equals(name)) {//如果标签名为merge                throw new InflateException("<merge /> must be the root element");  //merge标签只能作为根节点 //merge标签加载后会减少节点层级            } else {//如果根节点不存在,创建根节点,遍历子节点                final View view = createViewFromTag(parent, name, context, attrs);                final ViewGroup viewGroup = (ViewGroup) parent;                final ViewGroup.LayoutParams params = viewGroup.generateLayoutParams(attrs);                rInflateChildren(parser, view, attrs, true);                viewGroup.addView(view, params);            }        }        //解析merge标签时finishInflate为true        if (finishInflate) {            parent.onFinishInflate();} }




LayoutInflater解析的过程图,通过深度优先遍历:




0 0
原创粉丝点击