ViewRoot 继承自framelayout, 根布局
Window
DecorView
public void setContentView(@LayoutRes int layoutResID) {
getWindow().setContentView(layoutResID);//实际上是getWindow()在调用,
initWindowDecorActionBar();//设置ActionBar(不包含状态栏)
}
public Window getWindow() {
return mWindow;
}
// Window类的注释代码only existing implementation is PhoneWindow
public abstract class Window {//唯一的实现类是PhoneWindow
}
PhoneWindow的setContentView核心源码
if (mContentParent == null) {//mContentParent是viewgroup
installDecor();//初始化Decor
}
//设置我们的布局填充到mContentParent
mLayoutInflater.inflate(layoutResID, mContentParent);
这段代码说明了,实际上我们的布局文件之上,还有一个父容器viewgroup
private void installDecor() {
if (mDecor == null) {
mDecor = generateDecor(-1);//创建一个DecorView
//设置的属性和动画效果直接忽略
else {
mDecor.setWindow(this);//DecorView设置一个window
}
if (mContentParent == null) {
mContentParent = generateLayout(mDecor);
//如果viewgroup为空,则生成一个layout
generateDecor源码分析
protected DecorView generateDecor(int featureId) {
//内部就是new了一个DecorView。
return new DecorView(context, featureId, this, getAttributes());
}
generateLayout()源码分析
generateLayout内部实际上就是在setFlags和setLayout和style和requestFeature()和动画一系列的操作最终就是在创建一个DecorView。同时,也印证了,在设置getWindow.requestFeature时,为什么要设置在setContentView()之前,因为这些在之前就已经设置了。最后是会根据不同的状态去加载不同的布局
//最后会加载layoutResource
mDecor.onResourcesLoaded(mLayoutInflater, layoutResource);
onResourcesLoaded内部实际上就是把layoutResource填充进来
void onResourcesLoaded(LayoutInflater inflater, int layoutResource) {
final View root = inflater.inflate(layoutResource, null);
}
创建完父容器之后,再去填充我们自己的布局,底层是用的xml解析,解析过程(略)。
也就是说,setContentView()实际上就是两步
1.加载父容器(包括各种style和各类资源等),
2.加载自身布局
但是这里仅仅只是加载,正如我们最初在学activity生命周期时,很明确的说明,oncreate()只是在准备阶段,加载资源文件,也就是说,没有将view添加到window。因为oncrete中setContentView()仅仅只是资源准备阶段,只有当ActivityThread执行onReLauchActivity时,也就是onResume()方法时,才会将view添加到window中
下一篇,将会讲解,DecorView是如何添加到窗口window的源码分析