布局加載器加載視圖的方法有以下幾種:
- 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)
resource會(huì)通過(guò)Pull解析器被解析成XmlPullParser類型的parser, 故只需要看第四個(gè)方法就知道是怎么回事了!一般我們使用它的時(shí)候有三種使用方法:
- inflate(parser, null, false);
- inflate(parser, root, false);
- inflate(parser, root, true);
//在API25源碼復(fù)制
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;
}
}
- inflate(parser, null, false);
- inflate(parser, root, false);
- inflate(parser, root, true);
第一種情況:
// Decide whether to return the root that was passed in or the
// top view found in xml.
if (root == null || !attachToRoot) {
result = temp;
}
temp是啥筒繁?往前看:
// Temp is the root view that was found in the xml
final View temp = createViewFromTag(root, name, inflaterContext, attrs);
temp is the root view that was found in the xml.源碼中的注釋寫的很清晰噩凹。temp就是你加載的那個(gè)xml文件的根視圖巴元。也就是說(shuō)第二個(gè)參數(shù)root如果是空就直接返回xml文件里的根視圖毡咏。接下來(lái)看看root!=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);
}
...
// Decide whether to return the root that was passed in or the
// top view found in xml.
if (root == null || !attachToRoot) {
result = temp;
}
}
現(xiàn)在更清晰了,當(dāng)我們傳進(jìn)來(lái)的root不是null逮刨,并且第三個(gè)參數(shù)是false的時(shí)候呕缭,這個(gè)temp會(huì)使用root生成的layoutParams,并作為返回值返回了修己。而當(dāng)我們?cè)O(shè)置root為空的時(shí)候恢总,沒(méi)有設(shè)置LayoutParams參數(shù)的temp對(duì)象,作為返回值返回了睬愤。這時(shí)候我們發(fā)現(xiàn)只要是root為null或者attachToRoot為false都會(huì)將root返回片仿,那么inflate(parser, null, false)和inflate(parser, root, false)又有什么區(qū)別呢?實(shí)際上這個(gè)root是作為一個(gè)協(xié)助生成view的容器尤辱,如果我想讓生成的布局的根節(jié)點(diǎn)有效砂豌,又不想讓它處于某一個(gè)容器中,那我就可以設(shè)置root!=null光督,而attachToRoot為false阳距。由此可見(jiàn)root會(huì)協(xié)助第一個(gè)參數(shù)所指定布局的根節(jié)點(diǎn)生成布局參數(shù)!
??再回頭看代碼结借,當(dāng)root!=null,attachToRoot為true時(shí):
// 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);
}
很清楚筐摘,當(dāng)attachToRoot為true時(shí),會(huì)將第一個(gè)參數(shù)所指定的布局添加到第二個(gè)參數(shù)的View中。
??總結(jié)一下:當(dāng)root==null時(shí)咖熟,直接返回要加載布局文件的根視圖圃酵;當(dāng)root!=null時(shí),如果attachToRoot==false球恤,系統(tǒng)會(huì)通過(guò)將root作為一個(gè)容器,協(xié)助生成view咽斧;如果attachToRoot==true堪置,會(huì)將生成的view添加到root中。