1、setContentView作用
Set the activity content from a layout resource. The resource will be
inflated, adding all top-level views to the activity.
将布局资源文件设置activity上的内容,资源将会被渲染,添加到activity的顶级视图
2、源码分析
通过一个Activity的setContentView()方法展开
public void setContentView(@LayoutRes int layoutResID) {
// 通过window设置内容
getWindow().setContentView(layoutResID);
// 初始化ActionBar
initWindowDecorActionBar();
}
getWindow().setContentView(layoutResID);
通过getWindow()方法,获取window对象,并调用Window类中的setContentView(layoutResID)方法
public Window getWindow() {
return mWindow;
}
那么mWindow从哪里进行赋值的呢?
查看Activity源码中的attach方法,发现
mWindow = new PhoneWindow(this, window, activityConfigCallback);
可见那么mWindow是通过PhoneWindow来赋值的
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,
Window window, ActivityConfigCallback activityConfigCallback) {
attachBaseContext(context);
mFragments.attachHost(null /*parent*/);
mWindow = new PhoneWindow(this, window, activityConfigCallback);
mWindow.setWindowControllerCallback(this);
mWindow.setCallback(this);
mWindow.setOnWindowDismissedCallback(this);
mWindow.getLayoutInflater().setPrivateFactory(this);
Window类中的setContentView(layoutResID)方法
通过源码查看该方法是一个abstract方法,必然由其子类重写来实现具体操作
public abstract void setContentView(@LayoutRes int layoutResID);
PhoneWindow源码查看
public class PhoneWindow extends Window implements MenuBuilder.Callback {
果然PhoneWindow是Window的子类,需要重写SetContentView()方法
setContentView(layoutResID)
@Override
public void setContentView(int layoutResID) {
// mContentParent判空
if (mContentParent == null) {
installDecor();
} else if (!hasFeature(FEATURE_CONTENT_TRANSITIONS)) {
// 没有FEATURE_CONTENT_TRANSITIONS属性移除mContentParent中所有的views
mContentParent.removeAllViews();
}
// 如果具有FEATURE_CONTENT_TRANSITIONS属性
if (hasFeature(FEATURE_CONTENT_TRANSITIONS)) {
// 通过mContentParent、layoutResID、context获取Scence对象
final Scene newScene = Scene.getSceneForLayout(mContentParent, layoutResID,
getContext());
// 调用transitionTo方法将scence对象传递
transitionTo(newScene);
} else {
// 渲染资源文件
mLayoutInflater.inflate(layoutResID, mContentParent);
}
// 请求插入
mContentParent.requestApplyInsets();
//获取回调
final Callback cb = getCallback();
// 如果拥有回调并且未被销毁
if (cb != null && !isDestroyed()) {
// 回调contentChanged方法
cb.onContentChanged();
}
mContentParentExplicitlySet = true;
}
installDecor();
private void installDecor() {
mForceDecorInstall = false;
if (mDecor == null) {
// 生成mDecor也就是DecorView
mDecor = generateDecor(-1);
mDecor.setDescendantFocusability(ViewGroup.FOCUS_AFTER_DESCENDANTS);
mDecor.setIsRootNamespace(true);
if (!mInvalidatePanelMenuPosted && mInvalidatePanelMenuFeatures != 0) {
mDecor.postOnAnimation(mInvalidatePanelMenuRunnable);
}
} else {
// 将当前phoneWindow设置给decorView
mDecor.setWindow(this);
}
if (mContentParent == null) {
// 如果mContentParent为空,通过decor对象生成mContentParent
mContentParent = generateLayout(mDecor);
mDecor.makeOptionalFitsSystemWindows();
final DecorContentParent decorContentParent = (DecorContentParent)
// 通过id查询控件获取decorContentParent
mDecor.findViewById(
R.id.decor_content_parent);
if (decorContentParent != null) {
// 设置decorContentParent相关属性
} else {
// 设置title
// 根据style设置各种属性
}
generateDecor(-1);
protected DecorView generateDecor(int featureId) {
Context context;
if (mUseDecorContext) {
Context applicationContext = getContext().getApplicationContext();
if (applicationContext == null) {
context = getContext();
} else {
context = new DecorContext(applicationContext, getContext().getResources());
if (mTheme != -1) {
context.setTheme(mTheme);
}
}
} else {
context = getContext();
}
// 根据context、featureId、phoneWindow、attr创建decorView对象
return new DecorView(context, featureId, this, getAttributes());
}
generateLayout(mDecor);
protected ViewGroup generateLayout(DecorView decor) {
// 获取typeArray对象
TypedArray a = getWindowStyle();
// 读取style属性
// requestFeature
if (a.getBoolean(R.styleable.Window_windowNoTitle, false)) {
requestFeature(FEATURE_NO_TITLE);
// 省略部分相似功能代码......
// 根据属性设置Flag
if (a.getBoolean(R.styleable.Window_windowFullscreen, false)) {
setFlags(FLAG_FULLSCREEN, FLAG_FULLSCREEN & (~getForcedWindowFlags()));
}
// 省略部分相似功能代码......
// 设置状态栏颜色属性
if (!mForcedStatusBarColor) {
mStatusBarColor = a.getColor(R.styleable.Window_statusBarColor, 0xFF000000);
}
// 设置导航栏属性
if (!mForcedNavigationBarColor) {
mNavigationBarColor = a.getColor(R.styleable.Window_navigationBarColor, 0xFF000000);
mNavigationBarDividerColor = a.getColor(R.styleable.Window_navigationBarDividerColor,
0x00000000);
}
// 获取LayoutParams
WindowManager.LayoutParams params = getAttributes();
// 设置params属性
if (a.getBoolean(R.styleable.Window_backgroundDimEnabled,
mIsFloating)) {
/* All dialogs should have the window dimmed */
if ((getForcedWindowFlags()&WindowManager.LayoutParams.FLAG_DIM_BEHIND) == 0) {
params.flags |= WindowManager.LayoutParams.FLAG_DIM_BEHIND;
}
if (!haveDimAmount()) {
params.dimAmount = a.getFloat(
android.R.styleable.Window_backgroundDimAmount, 0.5f);
}
}
if (params.windowAnimations == 0) {
params.windowAnimations = a.getResourceId(
R.styleable.Window_windowAnimationStyle, 0);
}
// 渲染decorView
// Inflate the window decor.
int layoutResource;
int features = getLocalFeatures();
// 根据features获取resource资源
if ((features & (1 << FEATURE_SWIPE_TO_DISMISS)) != 0) {
layoutResource = R.layout.screen_swipe_dismiss;
setCloseOnSwipeEnabled(true);
} else if ((features & ((1 << FEATURE_LEFT_ICON) | (1 << FEATURE_RIGHT_ICON))) != 0) {
if (mIsFloating) {
TypedValue res = new TypedValue();
getContext().getTheme().resolveAttribute(
R.attr.dialogTitleIconsDecorLayout, res, true);
layoutResource = res.resourceId;
} else {
layoutResource = R.layout.screen_title_icons;
}
// XXX Remove this once action bar supports these features.
removeFeature(FEATURE_ACTION_BAR);
// System.out.println("Title Icons!");
} else if ((features & ((1 << FEATURE_PROGRESS) | (1 << FEATURE_INDETERMINATE_PROGRESS))) != 0
&& (features & (1 << FEATURE_ACTION_BAR)) == 0) {
// Special case for a window with only a progress bar (and title).
// XXX Need to have a no-title version of embedded windows.
layoutResource = R.layout.screen_progress;
// System.out.println("Progress!");
} else if ((features & (1 << FEATURE_CUSTOM_TITLE)) != 0) {
// Special case for a window with a custom title.
// If the window is floating, we need a dialog layout
if (mIsFloating) {
TypedValue res = new TypedValue();
getContext().getTheme().resolveAttribute(
R.attr.dialogCustomTitleDecorLayout, res, true);
layoutResource = res.resourceId;
} else {
layoutResource = R.layout.screen_custom_title;
}
// XXX Remove this once action bar supports these features.
removeFeature(FEATURE_ACTION_BAR);
} else if ((features & (1 << FEATURE_NO_TITLE)) == 0) {
// If no other features and not embedded, only need a title.
// If the window is floating, we need a dialog layout
if (mIsFloating) {
TypedValue res = new TypedValue();
getContext().getTheme().resolveAttribute(
R.attr.dialogTitleDecorLayout, res, true);
layoutResource = res.resourceId;
} else if ((features & (1 << FEATURE_ACTION_BAR)) != 0) {
layoutResource = a.getResourceId(
R.styleable.Window_windowActionBarFullscreenDecorLayout,
R.layout.screen_action_bar);
} else {
layoutResource = R.layout.screen_title;
}
// System.out.println("Title!");
} else if ((features & (1 << FEATURE_ACTION_MODE_OVERLAY)) != 0) {
layoutResource = R.layout.screen_simple_overlay_action_mode;
} else {
// Embedded, so no decoration is needed.
layoutResource = R.layout.screen_simple;
// System.out.println("Simple!");
}
// 开始改变decorView
mDecor.startChanging();
// 根据资源文件和mLayoutInflater将资源文件加载到decorView上
mDecor.onResourcesLoaded(mLayoutInflater, layoutResource);
ViewGroup contentParent = (ViewGroup)findViewById(ID_ANDROID_CONTENT);
if (contentParent == null) {
throw new RuntimeException("Window couldn't find content container view");
}
if ((features & (1 << FEATURE_INDETERMINATE_PROGRESS)) != 0) {
ProgressBar progress = getCircularProgressBar(false);
if (progress != null) {
progress.setIndeterminate(true);
}
}
if ((features & (1 << FEATURE_SWIPE_TO_DISMISS)) != 0) {
registerSwipeCallbacks(contentParent);
}
// Remaining setup -- of background and title -- that only applies
// to top-level windows.
if (getContainer() == null) {
final Drawable background;
if (mBackgroundResource != 0) {
background = getContext().getDrawable(mBackgroundResource);
} else {
background = mBackgroundDrawable;
}
// 设置背景
mDecor.setWindowBackground(background);
final Drawable frame;
if (mFrameResource != 0) {
frame = getContext().getDrawable(mFrameResource);
} else {
frame = null;
}
// 设置frame结构
mDecor.setWindowFrame(frame);
// 设置阴影
mDecor.setElevation(mElevation);
// 设置限定范围
mDecor.setClipToOutline(mClipToOutline);
if (mTitle != null) {
setTitle(mTitle);
}
if (mTitleColor == 0) {
mTitleColor = mTextColor;
}
setTitleColor(mTitleColor);
}
// 改变结束
mDecor.finishChanging();
// 返回viewGroup
return contentParent;
}
3、流程图