View.Inflate()和LayoutInflate填充布局详解

版权声明:转载请标明出处! https://blog.csdn.net/baidu_36619149/article/details/80930346

View.Inflate()和LayoutInflate填充布局详解

View.Inflate()

View.Inflate(Context context,int resource, ViewGroup root)

查看源码:

public static View inflate(Context context, @LayoutRes int resource, ViewGroup root) {
    LayoutInflater factory = LayoutInflater.from(context);
    return factory.inflate(resource, root);
}

可以看出其内部调用的 LayoutInflate 的两个参数方法

LayoutInflate填充布局

首先通过 LayoutInflater.from(this)获取 LayoutInflate 实例

LayoutInflater layoutInflater = LayoutInflater.from(this);

一般我们常用的调用方法如下:

layoutInflater.inflate(int resource, ViewGroup root);
layoutInflater.inflate(int resource, ViewGroup root, boolean attachToRoot);

1.两个参数的:layoutInflater.inflate(int resource, ViewGroup root);

    查看源码

public View inflate(@LayoutRes int resource, @Nullable ViewGroup root) {
       return inflate(resource, root, root != null);
     }

    其内部还是调用的三个参数的方法

2.三个参数的layoutInflater.inflate(int resource, ViewGroup root, boolean attachToRoot);
第一个参数:布局文件的id
第二个参数:根据第三个参数来决定是布局文件的父控件,还是只是为布局文件提供LayoutParams参数
第三个参数:是否依赖第二个控件成为其子控件

查看源码


layoutInflater.inflate(resource, null,false)

public View inflate(@LayoutRes int resource, @Nullable ViewGroup root, boolean attachToRoot) {
        final Resources res = getContext().getResources();
        if (DEBUG) {
            Log.d(TAG, "INFLATING from resource: \"" + res.getResourceName(resource) + "\" ("
                    + Integer.toHexString(resource) + ")");
        }

        final XmlResourceParser parser = res.getLayout(resource);
        try {
            return inflate(parser, root, attachToRoot);
        } finally {
            parser.close();
        }
    }
public View inflate(XmlPullParser parser, @Nullable ViewGroup root, boolean attachToRoot) {
        synchronized (mConstructorArgs) {
            Trace.traceBegin(Trace.TRACE_TAG_VIEW, "inflate");

            final Context inflaterContext = mContext;
            final AttributeSet attrs = Xml.asAttributeSet(parser);
            Context lastContext = (Context) mConstructorArgs[0];
            mConstructorArgs[0] = inflaterContext;
            View result = root;

            try {
                // Look for the root node.
                int type;
                while ((type = parser.next()) != XmlPullParser.START_TAG &&
                        type != XmlPullParser.END_DOCUMENT) {
                    // Empty
                }

                if (type != XmlPullParser.START_TAG) {
                    throw new InflateException(parser.getPositionDescription()
                            + ": No start tag found!");
                }

                final String name = parser.getName();

                if (DEBUG) {
                    System.out.println("**************************");
                    System.out.println("Creating root view: "
                            + name);
                    System.out.println("**************************");
                }

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

                    rInflate(parser, root, inflaterContext, attrs, false);
                } else {
                    // Temp is the root view that was found in the xml
                    final View temp = createViewFromTag(root, name, inflaterContext, attrs);

                    ViewGroup.LayoutParams params = null;
                    if (root != null) {
                        if (DEBUG) {
                            System.out.println("Creating params from root: " +
                                    root);
                        }
                        // Create layout params that match root, if supplied
                        params = root.generateLayoutParams(attrs);
                        if (!attachToRoot) {
                            // Set the layout params for temp if we are not
                            // attaching. (If we are, we use addView, below)
                            temp.setLayoutParams(params);
                        }
                    }

                    if (DEBUG) {
                        System.out.println("-----> start inflating children");
                    }

                    // Inflate all children under temp against its context.
                    rInflateChildren(parser, temp, attrs, true);

                    if (DEBUG) {
                        System.out.println("-----> done inflating children");
                    }

                    // We are supposed to attach all the views we found (int temp)
                    // to root. Do that now.
                    if (root != null && attachToRoot) {
                        root.addView(temp, params);
                    }

                    // Decide whether to return the root that was passed in or the
                    // top view found in xml.
                    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(parser.getPositionDescription()
                        + ": " + e.getMessage(), e);
                ie.setStackTrace(EMPTY_STACK_TRACE);
                throw ie;
            } finally {
                // Don't retain static reference on context.
                mConstructorArgs[0] = lastContext;
                mConstructorArgs[1] = null;

                Trace.traceEnd(Trace.TRACE_TAG_VIEW);
            }

            return result;
        }
    }

当第二个参数为null的时候,第三个参数为 true 或者 false 已经意义不大,布局文件中根布局的 layout_width 和 layout_height 都已经失效

	..........
    final View temp = createViewFromTag(root, name, inflaterContext, attrs);

	..........
 	if (root == null || !attachToRoot) {
            result = temp;
        }
	..........
	return result;

可以看出只是返回了View,并没有给其设置 LayoutParams

layoutInflater.inflate(resource, root,false)

	..........
    if (root != null) {
    	if (DEBUG) {
    		System.out.println("Creating params from root: " +
    	root);
    	 }
    	// Create layout params that match root, if supplied
    	params = root.generateLayoutParams(attrs);
    	 if (!attachToRoot) {
    	 // Set the layout params for temp if we are not
    	 // attaching. (If we are, we use addView, below)
    	 temp.setLayoutParams(params);
    	 }
     }
    	..........
    
    if (root == null || !attachToRoot) {
        result = temp;
    }
    	..........
    return result;

有源码可以看出第二个参数不为null,第三个参数为false,只是用root提供LayoutParams参数来获取,但是并没有给其指定父控件

layoutInflater.inflate(resource, root,true)

..........
 if (root != null) {
        if (DEBUG) {
            System.out.println("Creating params from root: " +
                            root);
         }
                // Create layout params that match root, if supplied
                params = root.generateLayoutParams(attrs);
         if (!attachToRoot) {
             // Set the layout params for temp if we are not
             // attaching. (If we are, we use addView, below)
             temp.setLayoutParams(params);
         }
 }
..........
if (root != null && attachToRoot) {
    root.addView(temp, params);
}
..........
return result;

可以看出将 temp 按照 params 参数添加到 root 控件中

切记

在我们使用 ListView 和 RecyclerView 的时候,填充布局时不能写成layoutInflater.inflate(resource, root,true),其第三个参数不能为true,否则将会报错!

参考文章: View inflate方法和LayoutInflater inflate方法的区别详解

                Android LayoutInflater深度解析 给你带来全新的认识

猜你喜欢

转载自blog.csdn.net/baidu_36619149/article/details/80930346
今日推荐