Android LayoutInflater
請先閱讀:
Android 源碼分析 - LayoutInflater創建View的流程分析
除此之外,需要補充的內容:
inflate 方法返回值和 LayoutParams 參數生成
public View inflate(XmlPullParser parser, @Nullable ViewGroup root, boolean attachToRoot) {
final Context inflaterContext = mContext;
final AttributeSet attrs = Xml.asAttributeSet(parser);
Context lastContext = (Context) mConstructorArgs[0];
mConstructorArgs[0] = inflaterContext;
// 返回值,默認為 root
View result = root;
// ...
// xml 生成的 view
final View temp = createViewFromTag(root, name, inflaterContext, attrs);
ViewGroup.LayoutParams params = null;
if (root != null) {
// 生成 View 的 LayoutParams,前提是傳入的root不為null
params = root.generateLayoutParams(attrs);
// 如果attachToRoot為 false,設置 LayoutParams
// 如果attachToRoot為 true,這里沒有必要設置,因為后面會 addView
if (!attachToRoot) {
temp.setLayoutParams(params);
}
}
rInflateChildren(parser, temp, attrs, true);
// 如果 attachToRoot,直接將 view 添加到 root
if (root != null && attachToRoot) {
root.addView(temp, params);
}else {
// 這里做了改寫,源代碼為 if (root == null || !attachToRoot),其實是一個意思
// 返回值是生成的 view
result = temp;
}
return result;
}
結論:
LayoutParams 參數生成:
root 參數不為 null,將被用來生成 view 的 LayoutParams 參數(調用 root.generateLayoutParams方法,各個 ViewGroup的之類有不同的自己的 LayoutParams 類型和構造方式);
如果 root 參數為 null,生成的 view 沒有 LayoutParams 參數,需要返回view后自己設置;
返回值:
-
如果root參數不為 null,attachToRoot 為 true 時,返回 root;
attachToRoot 為 false 時,返回生成的 view,這時該 view 并未添加到 root 中,需要手動添加;
-
如果 root 參數為 null,attachToRoot 為 true 和 false 情況下,請自行分析,沒有見到有人這么用過(這么使用沒有意義),應該也不是api設計者的初衷;
LayoutInflater 的實現類 及 xml 文件中未指定全類名的 View 如果找到構造方法
其實,不過通過什么方式,得到的構造方法均為PhoneLayoutInflater對象,該類部分代碼如下:
package com.android.internal.policy;
public class PhoneLayoutInflater extends LayoutInflater {
// 沒有全類名(沒有 "." 的類名),將嘗試添加這些前綴,其實還有另一個前綴
// "android.view."
private static final String[] sClassPrefixList = {
"android.widget.",
"android.webkit.",
"android.app."
};
@Override protected View onCreateView(String name, AttributeSet attrs) throws ClassNotFoundException {
for (String prefix : sClassPrefixList) {
try {
View view = createView(name, prefix, attrs);
if (view != null) {
return view;
}
} catch (ClassNotFoundException e) {
// In this case we want to let the base class take a crack
// at it.
}
}
// 這里調用了 父類的 onCreateView方法,其中只有一行代碼(return createView(name, "android.view.", attrs);)
return super.onCreateView(name, attrs);
}
}
Let's go change the world,or changed by the world
浙公網安備 33010602011771號