欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

XML布局嵌套多少层会导致OOM

程序员文章站 2022-06-16 10:10:04
查看setContentView源码可以看到,最终调用的是rInflate。首先遍历所有的节点,假如是普通的view就直接获取,是Viewgroup的话会调用rInflateChildren,发现在rInflateChildren里面调用的还是rInflate,是一个递归调用。而且没有退出条件,就会导致不断地进行压栈。类似这种情况,JVM 实际会抛出 *Error;当然,如果 JVM 试图去扩展栈空间的的时候失败,则会抛出 OutOfMemoryError。栈最多存放多少栈帧...

查看setContentView源码可以看到,最终调用的是rInflate。
首先遍历所有的节点,假如是普通的view就直接获取,是Viewgroup的话会调用rInflateChildren,
发现在rInflateChildren里面调用的还是rInflate,是一个递归调用。
而且没有退出条件,就会导致不断地进行压栈。类似这种情况,JVM 实际会抛出 *Error;当然,如果 JVM 试图去扩展栈空间的的时候失败,则会抛出 OutOfMemoryError。
栈最多存放多少栈帧取决于虚拟机设置的参数。

/**
     * Recursive method used to inflate internal (non-root) children. This
     * method calls through to {@link #rInflate} using the parent context as
     * the inflation context.
     * <strong>Note:</strong> Default visibility so the BridgeInflater can
     * call it.
     */
    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;
        boolean pendingRequestFocus = false;

        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)) {
                pendingRequestFocus = true;
                consumeChildElements(parser);
            } else if (TAG_TAG.equals(name)) {
                parseViewTag(parser, parent, attrs);
            } else if (TAG_INCLUDE.equals(name)) {
                if (parser.getDepth() == 0) {
                    throw new InflateException("<include /> cannot be the root element");
                }
                parseInclude(parser, context, parent, attrs);
            } else if (TAG_MERGE.equals(name)) {
                throw new InflateException("<merge /> must be the root element");
            } 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);
            }
        }

        if (pendingRequestFocus) {
            parent.restoreDefaultFocus();
        }

        if (finishInflate) {
            parent.onFinishInflate();
        }
    }

本文地址:https://blog.csdn.net/weixin_37165769/article/details/110958199