如题所述
第1个回答 2018-07-22
SetContentView
在activity的onCreate()生命周期函数中,会调用setContentView()来设置我们的布局文件,先来了解下setContentView()函数
public void setContentView(@LayoutRes int layoutResID) {
getWindow().setContentView(layoutResID);//调用了getWindow()
initWindowDecorActionBar();
}1234
间接调用了getWindow()的setContentView()函数,来看看getWindow()
public Window getWindow() { return mWindow;
}123
来看看mWindow是什么时候初始化的
final void attach(Context context, ActivityThread aThread,
Instrumentation instr, IBinder token, int ident,
Application application, Intent intent, ActivityInfo info,
CharSequence title, Activity parent, String id,
NonConfigurationInstances lastNonConfigurationInstances,
Configuration config, String referrer, IVoiceInteractor voiceInteractor) {
attachBaseContext(context); ...
mWindow = new PhoneWindow(this); ...
}1234567891011
在activity的attach()函数中初始化,是一个PhoneWindow,那接着而看看PhoneWindow的setContentView()方法
@Override
public void setContentView(int layoutResID) { // before this happens.
if (mContentParent == null) {
installDecor();
} else if (!hasFeature(FEATURE_CONTENT_TRANSITIONS)) {
mContentParent.removeAllViews();
} if (hasFeature(FEATURE_CONTENT_TRANSITIONS)) { final Scene newScene = Scene.getSceneForLayout(mContentParent, layoutResID,
getContext());
transitionTo(newScene);
} else {
mLayoutInflater.inflate(layoutResID, mContentParent);
}
mContentParent.requestApplyInsets(); final Callback cb = getCallback(); if (cb != null && !isDestroyed()) {
cb.onContentChanged();
}
}1234567891011121314151617181920212223
mContentParent为null时先调用 installDecor(),然后在通过mLayoutInflater.inflate(layoutResID, mContentParent);进行设置,先来看看installDecor()
private void installDecor() { //mDecor为null,进行初始化
if (mDecor == null) {
mDecor = generateDecor();
mDecor.setDescendantFocusability(ViewGroup.FOCUS_AFTER_DESCENDANTS);
mDecor.setIsRootNamespace(true); if (!mInvalidatePanelMenuPosted && mInvalidatePanelMenuFeatures != 0) {
mDecor.postOnAnimation(mInvalidatePanelMenuRunnable);
}
} //mContentParent为null,进行初始化
if (mContentParent == null) {
mContentParent = generateLayout(mDecor); // Set up decor part of UI to ignore fitsSystemWindows if appropriate.
mDecor.makeOptionalFitsSystemWindows(); final DecorContentParent decorContentParent = (DecorContentParent) mDecor.findViewById(
R.id.decor_content_parent); if (decorContentParent != null) {
mDecorContentParent = decorContentParent;
mDecorContentParent.setWindowCallback(getCallback()); if (mDecorContentParent.getTitle() == null) {
mDecorContentParent.setWindowTitle(mTitle);
} final int localFeatures = getLocalFeatures(); for (int i = 0; i < FEATURE_MAX; i++) { if ((localFeatures & (1 << i)) != 0) {
mDecorContentParent.initFeature(i);
}
}
mDecorContentParent.setUiOptions(mUiOptions); if ((mResourcesSetFlags & FLAG_RESOURCE_SET_ICON) != 0 ||
(mIconRes != 0 && !mDecorContentParent.hasIcon())) {
mDecorContentParent.setIcon(mIconRes);
} else if ((mResourcesSetFlags & FLAG_RESOURCE_SET_ICON) == 0 &&
mIconRes == 0 && !mDecorContentParent.hasIcon()) {
mDecorContentParent.setIcon(
getContext().getPackageManager().getDefaultActivityIcon());
mResourcesSetFlags |= FLAG_RESOURCE_SET_ICON_FALLBACK;
} if ((mResourcesSetFlags & FLAG_RESOURCE_SET_LOGO) != 0 ||
(mLogoRes != 0 && !mDecorContentParent.hasLogo())) {
mDecorContentParent.setLogo(mLogoRes);
}
PanelFeatureState st = getPanelState(FEATURE_OPTIONS_PANEL, false); if (!isDestroyed() && (st == null || st.menu == null) && !mIsStartingWindow) {
invalidatePanelMenu(FEATURE_ACTION_BAR);
}
} else { // mContentParent不为null
mTitleView = (TextView)findViewById(R.id.title); if (mTitleView != null) {
mTitleView.setLayoutDirection(mDecor.getLayoutDirection()); // 不显示标题的时候隐藏
if ((getLocalFeatures() & (1 << FEATURE_NO_TITLE)) != 0) {
View titleContainer = findViewById(
R.id.title_container); if (titleContainer != null) {
titleContainer.setVisibility(View.GONE);
} else {
mTitleView.setVisibility(View.GONE);
} if (mContentParent instanceof FrameLayout) {
((FrameLayout)mContentParent).setForeground(null);
}
} else { // 设置标题
mTitleView.setText(mTitle);
}
}
}
}
}1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980
DecorView为null时调用generateDecor()进行初始化DecorView,mContentParent为null时调用generateLayout(mDecor)初始化mContentParent,然后设置标题,若不显示标题则隐藏。
先来看看generateDecor()
protected DecorView generateDecor() { return new DecorView(getContext(), -1);
}1234
只是进行初始化DecorView,接着看generateLayout(mDecor)
protected ViewGroup generateLayout(DecorView decor) {
//...省略代码
//通过主题加载不同的布局文件
View in = mLayoutInflater.inflate(layoutResource, null);
//设置DecorView
decor.addView(in, new ViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT));
mContentRoot = (ViewGroup) in;
//获取contentParent
ViewGroup contentParent = (ViewGroup)findViewById(ID_ANDROID_CONTENT);
//...省略代码 return contentParent;
}12345678910111213
我们再回到PhoneWindow的setContentView()函数中
public void setContentView(int layoutResID) { if (mContentParent == null) {
installDecor();
} else if (!hasFeature(FEATURE_CONTENT_TRANSITIONS)) {
mContentParent.removeAllViews();
} if (hasFeature(FEATURE_CONTENT_TRANSITIONS)) { final Scene newScene = Scene.getSceneForLayout(mContentParent, layoutResID,
getContext());
transitionTo(newScene);
} else { //布局文件被设置到ContentParent
mLayoutInflater.inflate(layoutResID, mContentParent);
}
mContentParent.requestApplyInsets(); final Callback cb = getCallback(); if (cb != null && !isDestroyed()) {
cb.onContentChanged();
}
}
在activity的onCreate()生命周期函数中,会调用setContentView()来设置我们的布局文件,先来了解下setContentView()函数
public void setContentView(@LayoutRes int layoutResID) {
getWindow().setContentView(layoutResID);//调用了getWindow()
initWindowDecorActionBar();
}1234
间接调用了getWindow()的setContentView()函数,来看看getWindow()
public Window getWindow() { return mWindow;
}123
来看看mWindow是什么时候初始化的
final void attach(Context context, ActivityThread aThread,
Instrumentation instr, IBinder token, int ident,
Application application, Intent intent, ActivityInfo info,
CharSequence title, Activity parent, String id,
NonConfigurationInstances lastNonConfigurationInstances,
Configuration config, String referrer, IVoiceInteractor voiceInteractor) {
attachBaseContext(context); ...
mWindow = new PhoneWindow(this); ...
}1234567891011
在activity的attach()函数中初始化,是一个PhoneWindow,那接着而看看PhoneWindow的setContentView()方法
@Override
public void setContentView(int layoutResID) { // before this happens.
if (mContentParent == null) {
installDecor();
} else if (!hasFeature(FEATURE_CONTENT_TRANSITIONS)) {
mContentParent.removeAllViews();
} if (hasFeature(FEATURE_CONTENT_TRANSITIONS)) { final Scene newScene = Scene.getSceneForLayout(mContentParent, layoutResID,
getContext());
transitionTo(newScene);
} else {
mLayoutInflater.inflate(layoutResID, mContentParent);
}
mContentParent.requestApplyInsets(); final Callback cb = getCallback(); if (cb != null && !isDestroyed()) {
cb.onContentChanged();
}
}1234567891011121314151617181920212223
mContentParent为null时先调用 installDecor(),然后在通过mLayoutInflater.inflate(layoutResID, mContentParent);进行设置,先来看看installDecor()
private void installDecor() { //mDecor为null,进行初始化
if (mDecor == null) {
mDecor = generateDecor();
mDecor.setDescendantFocusability(ViewGroup.FOCUS_AFTER_DESCENDANTS);
mDecor.setIsRootNamespace(true); if (!mInvalidatePanelMenuPosted && mInvalidatePanelMenuFeatures != 0) {
mDecor.postOnAnimation(mInvalidatePanelMenuRunnable);
}
} //mContentParent为null,进行初始化
if (mContentParent == null) {
mContentParent = generateLayout(mDecor); // Set up decor part of UI to ignore fitsSystemWindows if appropriate.
mDecor.makeOptionalFitsSystemWindows(); final DecorContentParent decorContentParent = (DecorContentParent) mDecor.findViewById(
R.id.decor_content_parent); if (decorContentParent != null) {
mDecorContentParent = decorContentParent;
mDecorContentParent.setWindowCallback(getCallback()); if (mDecorContentParent.getTitle() == null) {
mDecorContentParent.setWindowTitle(mTitle);
} final int localFeatures = getLocalFeatures(); for (int i = 0; i < FEATURE_MAX; i++) { if ((localFeatures & (1 << i)) != 0) {
mDecorContentParent.initFeature(i);
}
}
mDecorContentParent.setUiOptions(mUiOptions); if ((mResourcesSetFlags & FLAG_RESOURCE_SET_ICON) != 0 ||
(mIconRes != 0 && !mDecorContentParent.hasIcon())) {
mDecorContentParent.setIcon(mIconRes);
} else if ((mResourcesSetFlags & FLAG_RESOURCE_SET_ICON) == 0 &&
mIconRes == 0 && !mDecorContentParent.hasIcon()) {
mDecorContentParent.setIcon(
getContext().getPackageManager().getDefaultActivityIcon());
mResourcesSetFlags |= FLAG_RESOURCE_SET_ICON_FALLBACK;
} if ((mResourcesSetFlags & FLAG_RESOURCE_SET_LOGO) != 0 ||
(mLogoRes != 0 && !mDecorContentParent.hasLogo())) {
mDecorContentParent.setLogo(mLogoRes);
}
PanelFeatureState st = getPanelState(FEATURE_OPTIONS_PANEL, false); if (!isDestroyed() && (st == null || st.menu == null) && !mIsStartingWindow) {
invalidatePanelMenu(FEATURE_ACTION_BAR);
}
} else { // mContentParent不为null
mTitleView = (TextView)findViewById(R.id.title); if (mTitleView != null) {
mTitleView.setLayoutDirection(mDecor.getLayoutDirection()); // 不显示标题的时候隐藏
if ((getLocalFeatures() & (1 << FEATURE_NO_TITLE)) != 0) {
View titleContainer = findViewById(
R.id.title_container); if (titleContainer != null) {
titleContainer.setVisibility(View.GONE);
} else {
mTitleView.setVisibility(View.GONE);
} if (mContentParent instanceof FrameLayout) {
((FrameLayout)mContentParent).setForeground(null);
}
} else { // 设置标题
mTitleView.setText(mTitle);
}
}
}
}
}1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980
DecorView为null时调用generateDecor()进行初始化DecorView,mContentParent为null时调用generateLayout(mDecor)初始化mContentParent,然后设置标题,若不显示标题则隐藏。
先来看看generateDecor()
protected DecorView generateDecor() { return new DecorView(getContext(), -1);
}1234
只是进行初始化DecorView,接着看generateLayout(mDecor)
protected ViewGroup generateLayout(DecorView decor) {
//...省略代码
//通过主题加载不同的布局文件
View in = mLayoutInflater.inflate(layoutResource, null);
//设置DecorView
decor.addView(in, new ViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT));
mContentRoot = (ViewGroup) in;
//获取contentParent
ViewGroup contentParent = (ViewGroup)findViewById(ID_ANDROID_CONTENT);
//...省略代码 return contentParent;
}12345678910111213
我们再回到PhoneWindow的setContentView()函数中
public void setContentView(int layoutResID) { if (mContentParent == null) {
installDecor();
} else if (!hasFeature(FEATURE_CONTENT_TRANSITIONS)) {
mContentParent.removeAllViews();
} if (hasFeature(FEATURE_CONTENT_TRANSITIONS)) { final Scene newScene = Scene.getSceneForLayout(mContentParent, layoutResID,
getContext());
transitionTo(newScene);
} else { //布局文件被设置到ContentParent
mLayoutInflater.inflate(layoutResID, mContentParent);
}
mContentParent.requestApplyInsets(); final Callback cb = getCallback(); if (cb != null && !isDestroyed()) {
cb.onContentChanged();
}
}