inflate(resource, root) 相当于 inflate(resource, root, root!=null) , 而后者的返回值由root决定,如果root不为空,会把root的布局信息设给xml对应的view,如果同时attachToRoot还是true,则把View添加到root里面,然后返回root,如果不是,最后返回xml对应的View!
结论如上,现在,我们一步步来看下,首先看四行代码:
public View inflate(int resource, ViewGroup root) public View inflate(int resource, ViewGroup root, boolean attachToRoot) public View inflate(XmlPullParser parser, ViewGroup root) public View inflate(XmlPullParser parser, ViewGroup root, boolean attachToRoot)
其中,1和2我们平时很常见,但核心是4,无论1还是2,最终都调用4,3也调用4!请看原码:
public View inflate(@LayoutRes int resource, @Nullable ViewGroup root) { return inflate(resource, root, root != null); }
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) { return inflate(parser, root, root != null); }
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; } }
第1段代码调用第2段代码,第2段代码调用第4段代码,当然,第3段代码也调用第4段代码!对于第4段代码,它返回result,而result最初赋值root,然后再看root,相关的核心代码有2段,先看第一段:
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); } }
这里如果root不为空,则把root的布局信息设给xml的布局,上面的tmp便是xml文件对应的view!
现在看第二段:
// 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; }
这里,如果root不为null,而且attachToRoot,则把tmp添加到root里面,如果不是则把tmp赋值给result,最后返回result!这里的attachToRoot便是上文刚开始时提到的attachToRoot经过查看这段原码,我们得出这样的结论:
inflate(resource, root) 相当于 inflate(resource, root, root!=null) , 而后者的返回值由root决定,如果root不为空,会把root的布局信息设给xml对应的view,如果同时attachToRoot还是true,则把View添加到root里面,然后返回root,如果不是,最后返回xml对应的View!