Android LayoutInflater源码分析

LayoutInflater分析

获取LayoutInflater对象

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

inflate方法参数说明

public View inflate(@LayoutRes int resource, @Nullable ViewGroup root, boolean attachToRoot) 
resource root attachToRoot 说明
XML布局 root == null 失去作用 由于子View的宽高属性是相对于父View的,没有指定父View,所以导致他的宽高属性失效。
XML布局 root != null attachToRoot == true 会将子View添加到父View中
XML布局 root != null attacthToRoot == false 会将子View外层的layout属性进行设置,子View被添加到父View中时,这些layout属性会自动生效。

源码分析

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

案例说明

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" />

当 root == null

View view = layoutInflater.inflate(R.layout.layout_btn, null);
ViewGroup.LayoutParams layoutParams = view.getLayoutParams();
linearLayout.addView(view);
在这里插入图片描述

当 root != null && attachToRoot == true

View view = layoutInflater.inflate(R.layout.layout_btn, linearLayout, true);
ViewGroup.LayoutParams layoutParams = view.getLayoutParams();
在这里插入图片描述

当 root != null && attachToRoot == false

View view = layoutInflater.inflate(R.layout.layout_btn, linearLayout, false);
ViewGroup.LayoutParams layoutParams = view.getLayoutParams();
linearLayout.addView(view);
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_14876133/article/details/106457683
今日推荐