1、Activity 中 onCreate()方法中 调用setContentView();
2、setContentView();
实际: AppCompatAcivity中加载View @Override public void setContentView(@LayoutRes int layoutResID) {
getDelegate().setContentView(layoutResID);
}
@Override public void setContentView(int resId) {
ensureSubDecor();
ViewGroup contentParent = (ViewGroup) mSubDecor.findViewById(android.R.id.content);
contentParent.removeAllViews();
LayoutInflater.from(mContext).inflate(resId, contentParent);
mOriginalWindowCallback.onContentChanged();
}
private void ensureSubDecor() { if (!mSubDecorInstalled) { mSubDecor = createSubDecor();
// If a title was set before we installed the decor, propagate it now
CharSequence title = getTitle();
if (!TextUtils.isEmpty(title)) {
onTitleChanged(title);
}
applyFixedSizeWindow();
onSubDecorInstalled(mSubDecor);
mSubDecorInstalled = true;
// Invalidate if the panel menu hasn't been created before this.
// Panel menu invalidation is deferred avoiding application onCreateOptionsMenu
// being called in the middle of onCreate or similar.
// A pending invalidation will typically be resolved before the posted message
// would run normally in order to satisfy instance state restoration.
PanelFeatureState st = getPanelState(FEATURE_OPTIONS_PANEL, false);
if (!isDestroyed() && (st == null || st.menu == null)) {
invalidatePanelMenu(FEATURE_SUPPORT_ACTION_BAR);
}
}
}
private ViewGroup createSubDecor() {
........
// Now set the Window's content view with the decor
mWindow.setContentView(subDecor);
........
return subDecor;
}
Activity 中的 public void setContentView(@LayoutRes int layoutResID) {
getWindow().setContentView(layoutResID);
initWindowDecorActionBar();
}
Window 是在 Activity中的attach中直接new PhoneWindow()出来的
LayoutInflater 在PhoneWindow构造函数中 new 出来的; public PhoneWindow(Context context) {
super(context);
mLayoutInflater = LayoutInflater.from(context);
}
XmlResourceParser 使用的是Pull解析
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();
}
}
XmlResourceParser通过Pull解析,获取节点,得到节点的控件名,通过反射生成View控件,递归生成View添加ViewGroup中
总结: 1.通过Activity的setContentView方法间接调用Phonewindow的setContentView(),在PhoneWindow中通过getLayoutInflate()得到LayoutInflate对象
2.通过LayoutInflate对象去加载View,主要步骤是
(1)通过xml的Pull方式去解析xml布局文件,获取xml信息,并保存缓存信息,因为这些数据是静态不变的
(2)根据xml的tag标签通过反射创建View逐层构建View
(3)递归构建其中的子View,并将子View添加到父ViewGroup中;