當(dāng)我們在自定義布局或者在RecyclerView的onBindViewHolder方法中使用下面的方法進(jìn)行布局加載
View view = View.inflate(parent.getContext(), R.layout.item_layout, null);
但是上面的方法中ViewGroup的參數(shù)到底是傳值呢,還是不傳呢捣郊?
并且和View view= LayoutInflater.from(context).inflate(R.layout.item_layout, parent, false);
這個又有啥區(qū)別呢?
現(xiàn)在我們進(jìn)行源碼分析
- 進(jìn)入View的inflate方法
public static View inflate(Context context, @LayoutRes int resource, ViewGroup root) {
LayoutInflater factory = LayoutInflater.from(context);
return factory.inflate(resource, root);
}
發(fā)現(xiàn)原來最終是使用LayoutInflater.from(context).inflate(resource, root);
來調(diào)用的inflate方法
2.繼續(xù)進(jìn)入是LayoutInflater類的inflate方法,如下:
public View inflate(@LayoutRes int resource, @Nullable ViewGroup root) {
return inflate(resource, root, root != null);
}
這里又是調(diào)用的是inflate(resource,root,root!= null);
雖然前面沒有attachToRoot這個參數(shù),但是在這里有調(diào)用了帶attachToRoot這個參數(shù)的方法,并且根據(jù)root的是否為null傳入該參數(shù)赏廓。
3.繼續(xù)進(jìn)入inflate方法
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();
}
}
到這里才是才是所有的方法的入口巴刻,這個方法中主要是把傳入的布局進(jìn)行解析
4.進(jìn)入inflate(parser,root,attachToRoot);
方法愚铡,這個方法中主要做了
public View inflate(XmlPullParser parser, @Nullable ViewGroup root, boolean attachToRoot) {
synchronized (mConstructorArgs) {
....
View result = root;
....
if (TAG_MERGE.equals(name)) {
....
} 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) {
// 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);
}
}
// Inflate all children under temp against its context.
rInflateChildren(parser, temp, attrs, true);
// 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;
}
}
.....
return result;
}
}
進(jìn)行分析,View result = root,且ViewGroup的LayoutParams首先會被設(shè)置為null胡陪,
①當(dāng)root為null或者attachToRoot為false時沥寥,ViewGroup的LayoutParams會為null,并將temp賦值給result進(jìn)行返回柠座。
②當(dāng)root不為null時邑雅,params才會被賦值,同時attachToRoot為false時才會把params設(shè)置給temp妈经,temp是啥淮野?就是根據(jù)inflate傳遞的參數(shù)生成的view捧书。
③當(dāng)root不為null時,同時attachToRoot為true時骤星,會調(diào)用root.addView(temp, params);
這里也就是當(dāng)我們在RecyclerView的onCreateViewHolder方法中使用View inflate = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_layout, parent, true);
時會報下面這個錯:
java.lang.IllegalStateException: The specified child already has a parent. You must call removeView() on the child's parent first.