Android LayoutInflater

2019-01-18  本文已影响0人  Android_冯星

参考文章

Android LayoutInflater原理分析,带你一步步深入了解View(一)

Android LayoutInflater源码解析

请直接观看上面的文章。下面的可以不必看。

记录

LayoutInflater 的作用就是将XML布局文件实例化为相应的 View 对象

总结

  1. LayoutInflater的内部实现方式,主要是pull解析布局文件
  2. attachToRoot参数作用
  1. 通过标签以反射的方式来创建 View 对象;

  2. 加载xml布局的原理
    其实就是从根节点开始,递归解析xml的每个节点,每一步递归的过程是:通过节点名称(全类名),使用ClassLoader创建对应类的实例,也就是View,然后,将这个View添加到它的上层节点(父View)。并同时会解析对应xml节点的属性作为View的属性。每个层级的节点都会被生成一个个的View,并根据View的层级关系add到对应的直接父View(上层节点)中,最终返回一个包含了所有解析好的子View的布局根View。

为什么view嵌套view多了会造成卡顿?

public void setContentView(int resId) {
        this.ensureSubDecor();
        ViewGroup contentParent = (ViewGroup)this.mSubDecor.findViewById(16908290);
        contentParent.removeAllViews();
        LayoutInflater.from(this.mContext).inflate(resId, contentParent);
        this.mOriginalWindowCallback.onContentChanged();
    }

setContentView方式内部也是使用LayoutInflater把布局加入到FrameLayout布局中的,而根据上面两篇文章,说到

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

这个方式使用了递归算法,在这里

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

如果嵌套层次过多,是会造成显示过慢。
当然使用LayoutInflater只是卡顿众多原因的一个,还有View的测量和绘制都是递归实现的。

递归调用效率问题,递归与循环比较

上一篇下一篇

猜你喜欢

热点阅读