Activity的界面添加到屏幕的流程
1、创建顶层布局容器DecorView(FrameLayout)
2、在DecorView中加载/基础布局/得到内部的ViewGroup
3、在/基础布局/中添加自己写的ContentView(即Activity的界面)
具体流程(源码分析:方法的调用)
- Activity中调用setContentView()方法
public void setContentView(@LayoutRes int layoutResID) {
getWindow().setContentView(layoutResID);
initWindowDecorActionBar();
}
getWindow():PhoneWindow对象
- 调用PhoneWindow对象的setContentView()方法
//PhoneWindow.java
@Override
public void setContentView(int layoutResID) {
if (mContentParent == null) {
installDecor();//调用方法初始化Decor
} else if (!hasFeature(FEATURE_CONTENT_TRANSITIONS)) {
mContentParent.removeAllViews();
}
//无关代码
}
- installDecor()方法:创建decorVIew
//PhoneWindow.java
private void installDecor() {
mForceDecorInstall = false;
if (mDecor == null) {
mDecor = generateDecor(-1);//返回DecorView
//无关代码
}
//无关代码
}
调用generateDecor()方法,返回一个DecorView对象
DecorView就是顶层布局,他是一个FrameLayout,第一个父布局产生!!!
- installDecor()方法:创建mContentParent(ViewGroup)
//PhoneWindow.java
private void installDecor() {
if (mContentParent == null) {
mContentParent = generateLayout(mDecor);//创建基础布局方法
//无关代码
}
//无关代码
}
mContentParent:一个ViewGroup对象,从字面上就看出是我们要加载content的parent布局(ViewGroup)
- generateLayout()方法:返回mContentParent(ViewGroup)
// Inflate the window decor.
int layoutResource;
...
//layoutResource根据不同的显示效果,赋值不同的布局文件
...
mDecor.onResourcesLoaded(mLayoutInflater, layoutResource);
ViewGroup contentParent = (ViewGroup)findViewById(ID_ANDROID_CONTENT);
...
return contentParent;
赋值layoutResource(布局文件),再把该布局文件添加到DecorView中,第二个基础布局创建完成!!!
不同的布局文件中总是存在一个id叫:/com.android.internal.R.id.content/ 的ViewGroup。
contentParent通过findViewById找到该id的控件,并返回。
DecorView(FrameLayout)中嵌套一个基础布局,
基础布局中包含一个id(/com.android.internal.R.id.content/)的ViewGroup
- mContentParent中添加Activity的的布局文件
//PhoneWindow.java
@Override
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 {
mLayoutInflater.inflate(layoutResID, mContentParent);
}
}
mContentParent作为parent,在解析Activity的layout中传入。最终显示到屏幕上。
总结
创建DecorView:PhoneWindow对象 -> installDecor() -> generateDecor() -> 得到DecorView
创建mContentParent:generateLayout() -> decorView关联基础布局(xml) -> findViewById(R.id.content) -> 得到mContentParent
Activity的布局放入mContentParent:setContentView()中,inflate(layoutResID,mContentParent)
网友评论