公子姓王

导航

Android LayoutInflater

请先阅读:

Android LayoutInflater源码解析

Android 源码分析 - LayoutInflater创建View的流程分析

除此之外,需要补充的内容:

inflate 方法返回值和 LayoutParams 参数生成

    public View inflate(XmlPullParser parser, @Nullable ViewGroup root, boolean attachToRoot) {
        final Context inflaterContext = mContext;
        final AttributeSet attrs = Xml.asAttributeSet(parser);
        Context lastContext = (Context) mConstructorArgs[0];
        mConstructorArgs[0] = inflaterContext;
        // 返回值,默认为 root
        View result = root;
        // ...
        // xml 生成的 view
        final View temp = createViewFromTag(root, name, inflaterContext, attrs);
        ViewGroup.LayoutParams params = null;
        if (root != null) {
            // 生成 View 的 LayoutParams,前提是传入的root不为null
            params = root.generateLayoutParams(attrs);
            // 如果attachToRoot为 false,设置 LayoutParams
            // 如果attachToRoot为  true,这里没有必要设置,因为后面会 addView
            if (!attachToRoot) {
                temp.setLayoutParams(params);
            }
        }
        rInflateChildren(parser, temp, attrs, true);
        // 如果 attachToRoot,直接将 view 添加到 root
        if (root != null && attachToRoot) {
            root.addView(temp, params);
        }else {
            // 这里做了改写,源代码为 if (root == null || !attachToRoot),其实是一个意思
            // 返回值是生成的 view
            result = temp;
        }
        return result;
    }

结论:

LayoutParams 参数生成:

root 参数不为 null,将被用来生成 view 的 LayoutParams 参数(调用 root.generateLayoutParams方法,各个 ViewGroup的之类有不同的自己的 LayoutParams 类型和构造方式);

如果 root 参数为 null,生成的 view 没有 LayoutParams 参数,需要返回view后自己设置;

返回值:

  1. 如果root参数不为 null,attachToRoot 为 true 时,返回 root;

    attachToRoot 为 false 时,返回生成的 view,这时该 view 并未添加到 root 中,需要手动添加;

  2. 如果 root 参数为 null,attachToRoot 为 true 和 false 情况下,请自行分析,没有见到有人这么用过(这么使用没有意义),应该也不是api设计者的初衷;

LayoutInflater 的实现类 及 xml 文件中未指定全类名的 View 如果找到构造方法

其实,不过通过什么方式,得到的构造方法均为PhoneLayoutInflater对象,该类部分代码如下:

package com.android.internal.policy;
public class PhoneLayoutInflater extends LayoutInflater {
    // 没有全类名(没有 "." 的类名),将尝试添加这些前缀,其实还有另一个前缀
  	// "android.view."
    private static final String[] sClassPrefixList = {
        "android.widget.",
        "android.webkit.",
        "android.app."
    };
    
    @Override protected View onCreateView(String name, AttributeSet attrs) throws ClassNotFoundException {
        for (String prefix : sClassPrefixList) {
            try {
                View view = createView(name, prefix, attrs);
                if (view != null) {
                    return view;
                }
            } catch (ClassNotFoundException e) {
                // In this case we want to let the base class take a crack
                // at it.
            }
        }
        // 这里调用了 父类的 onCreateView方法,其中只有一行代码(return createView(name, "android.view.", attrs);)
        return super.onCreateView(name, attrs);
    }
    
}

posted on 2020-02-15 13:42  公子姓王  阅读(235)  评论(0编辑  收藏  举报