在Android中,每个控件都有一块矩形的视图。控件大致分为两类:View和ViewGroup,它们的父类叫做ViewParent。那么View和ViewGroup有何区别吗?简单说,ViewGroup里可以包含View并管理它。通过ViewGroup,整个界面的控件形成了一个属性结构,这就说常言中的控件树。在程序中,这种结构有很多。控件树上层控件负责它包含的子空间的测量与绘制,并实现交互与时间传递。在Android中,R资源文件中包含所有的ID,我们的findViewById()方法就是在控件树中遍历查找对应的控件来进行其他操作。而在每个控件树的顶部,都有一个ViewParent对象,这就是整个ViewGroup最核心的部分,。
![View的树形结构图](https://i-blog.csdnimg.cn/blog_migrate/d93714f5945e03ab77949c545dbc8ed4.png)
我们在写布局的时候,通常在OnCreate方法中setContentView()来放置一个布局文件,之后,布局才能显示出来。那么这个方法具体做了哪些工作呢?在Activity内,我们知道都有一个Window管理器对象,那它又是做什么的呢?
![视图架构图](https://i-blog.csdnimg.cn/blog_migrate/d9eb2e45db9b6fe94182342868115095.png)
在Android中,Window对象是由PhoneWindow来实现的,PhoneWindow将一个DecorView设置为整个应用视图的根View,在DecorView中,封装了一些窗口操作的API。简单来说,DecorView将要显示的具体内容呈现在PhoneWindow上,它的子控件View的监听都通过WindowManagerService来进行接收,并通过Activity对象来回调相应的onClickListener。在显示的图层上,分为两部分,TitleView和ContentView。如此,就到了我们最熟悉的ContentView了。
![标准视图树](https://i-blog.csdnimg.cn/blog_migrate/9d40bdbd92453916fb58051c0de71149.png)
如上图所示,视图树的第二层装载了一个LinearLayout,这层的布局结构会根据相应的参数设置不同的布局,如我们最常用的,上面是一个ToolBar,下面是一个ContentView。我们知道,在setContentView()之前,通过设置requestWindowFeature(Window.FEATURE_NO_TITLE)可以设置去全屏显示,它的根本的道理就在这里了,只有在设置布局前,将TitleBar隐藏掉,这样布局中才能只有一个ContentView。这也就解释了为什么调用requestWindowFeature(Window.FEATURE_NO_TITLE)方法时一定要在setContentView()之前才生效的原因。
在OnCreate执行setContentView()方法后,ActivityManagerService会回调OnResume方法,此时系统才会把整个DecorVIew添加到PhoneWindow中并显示出来,这样才完成了界面的绘制。