Android LayoutInflater source code analysis

LayoutInflater analysis

Get the LayoutInflater object

LayoutInflater layoutInflater = LayoutInflater.from(context);
LayoutInflater layoutInflater = activity.getLayoutInflater();
//本质都是调用第三种方式
LayoutInflater layoutInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);

Inflate method parameter description

public View inflate(@LayoutRes int resource, @Nullable ViewGroup root, boolean attachToRoot) 
resource root attachToRoot Description
XML layout root == null Out of action Since the width and height attributes of the child View are relative to the parent View, and the parent View is not specified, its width and height attributes are invalidated.
XML layout root != null attachToRoot == true Will add the child View to the parent View
XML layout root != null attacthToRoot == false The layout attributes of the outer layer of the child View will be set. When the child View is added to the parent View, these layout attributes will take effect automatically.

Source code analysis

public View inflate(@LayoutRes int resource, @Nullable ViewGroup root, boolean attachToRoot) {
    
    
    final Resources res = getContext().getResources();
    //1.使用反射尝试获取提前编译好的View对象
    //2.如果获取到View对象,则直接返回;如果没有获取到,则通过XML资源解析器
    View view = tryInflatePrecompiled(resource, res, root, attachToRoot);
    if (view != null) {
    
    
        return view;
    }

    //根据资源id获取XML布局解析器
    XmlResourceParser parser = res.getLayout(resource);
    try {
    
    
        //使用XML解析器对XML布局进行解析
        return inflate(parser, root, attachToRoot);
    } finally {
    
    
        parser.close();
    }
}
public View inflate(XmlPullParser parser, @Nullable ViewGroup root, boolean attachToRoot) {
    
    
    synchronized (mConstructorArgs) {
    
    
        final Context inflaterContext = mContext;
        final AttributeSet attrs = Xml.asAttributeSet(parser);
        Context lastContext = (Context) mConstructorArgs[0];
        mConstructorArgs[0] = inflaterContext;
        View result = root;

        try {
    
    
            advanceToRootNode(parser);
            final String name = parser.getName();

            //如果布局根标签为merge,则root不能为null,attachToRoot不能为false,否则抛出异常
            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");
                }
                //解析XML布局
                rInflate(parser, root, inflaterContext, attrs, false);
            } else {
    
    
                //根据XML解析获取根View对象
                final View temp = createViewFromTag(root, name, inflaterContext, attrs);
                ViewGroup.LayoutParams params = null;

                //如果root不为null
                if (root != null) {
    
    
                    //获取root的布局参数
                    params = root.generateLayoutParams(attrs);
                    if (!attachToRoot) {
    
    
                        //如果attachToRoot==false,则View设置布局参数
                        temp.setLayoutParams(params);
                    }
                }

                //解析子布局
                rInflateChildren(parser, temp, attrs, true);

                //如果root!=null,且attachToRoot==true,则自动将布局添加到root中,并设置布局参数
                if (root != null && attachToRoot) {
    
    
                    root.addView(temp, params);
                }

                //当root==null或者attachToRoot==false,则直接返回View对象
                if (root == null || !attachToRoot) {
    
    
                    result = temp;
                }
            }

        } catch (XmlPullParserException e) {
    
    
            final InflateException ie = new InflateException(e.getMessage(), e);
            ie.setStackTrace(EMPTY_STACK_TRACE);
            throw ie;
        } catch (Exception e) {
    
    
            final InflateException ie = new InflateException(
                getParserStateDescription(inflaterContext, attrs)
                + ": " + e.getMessage(), e);
            ie.setStackTrace(EMPTY_STACK_TRACE);
            throw ie;
        } finally {
    
    
            mConstructorArgs[0] = lastContext;
            mConstructorArgs[1] = null;
            Trace.traceEnd(Trace.TRACE_TAG_VIEW);
        }
        return result;
    }
}

Case description

layout_btn

<?xml version="1.0" encoding="utf-8"?>
<Button xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="200dp"
        android:layout_height="200dp"
        android:orientation="vertical"
        android:text="hello" />

When root == null

View view = layoutInflater.inflate(R.layout.layout_btn, null);
ViewGroup.LayoutParams layoutParams = view.getLayoutParams();
linearLayout.addView(view);
Insert picture description here

当 root != null && attachToRoot == true

View view = layoutInflater.inflate(R.layout.layout_btn, linearLayout, true);
ViewGroup.LayoutParams layoutParams = view.getLayoutParams();
Insert picture description here

当 root != null && attachToRoot == false

View view = layoutInflater.inflate(R.layout.layout_btn, linearLayout, false);
ViewGroup.LayoutParams layoutParams = view.getLayoutParams();
linearLayout.addView(view);
Insert picture description here

Guess you like

Origin blog.csdn.net/qq_14876133/article/details/106457683