我们打开IDE创建一个Activity,IDE会自动帮我们生成一些代码,然后一个空的Activity界面就展示出来了。这一看似简单的问题,实则包含了很多内容,这一过程包含了Activity Window View三者之间复杂的三角关系,在这一流程中Activity是整个模型的控制单元,Window属于承载模型,负责承载视图,View是视图显示模型。
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
}
Activity的启动过程很复杂,最终会由ActivityThread中的performLaunchActivity()来完成整个启动过程,在这个方法的内部会通过类加载器创建Activity的实例对象,并调用其attach方法为其关联运行过程中所依赖的一系列上下文换件变量。在Activity的attach方法里,系统会创建Activity所属的Window对象并为其设置回调接口,Window对象的创建时通过PolicyManager的makeNewWindow方法实现的。由于Activity实现了Window的Callback接口,因此当Window接收到外界的状态改变就会回调到Activity的方法。
View是Android中的视图呈现方式,但是View不能单独存在,它必须附着在Window这个抽象的概念上面,因此有视图的地方就有Window。那些地方有视图呢?Android中可以提供视图的地方有Activity,DIalog,Toast,除此之外,还有一些依托Window而实现的视图,比如PopupWindow,Meun,他们也是视图,有视图的地方就有Window,因此Activity,Dialog,Toast等视图都对应着一个Window。
那View是怎样绑定在Window上的呢?还要介绍下Window和View之间的纽带:ViewRoot。ViewRoot对应于ViewRootImpl类,它是连接WindowManager和Decorview的纽带,View的三大流程(measure,layout,draw)均是通过ViewRoot来完成的。在ActivityThread中,当Activity对象被创建完毕后,会将DecorVidew添加到Window中,同时会创建ViewRootImpl对象,并将ViewRootImpl对象和DecorView建立关联。
root=new ViewRootImpl(view.getContext),display);
root.setView(view,wparams,panelParentView);
View的绘制流程是从ViewRoot的performTraversals方法开始的,它经过measure,layout和draw三个过程最终将一个View绘制出来,其中measure用来测量View的宽和高,layout用来确定View在父容器中的放置位置,而draw则负责将View绘制在屏幕上。如此反复完成一棵View树的遍历,整个View视图就显示在屏幕上了。
在onCreat()中,我们只有一个setContentView()的操作,在Activity的setContentView的实现可以看出,Activity将具体实现交给了Window处理,而Window的具体实现是PhoneWind在setContentView中创建了DecorView,DecorView是整棵View树的顶级View,然后将View添加到DecorView的mContentParent中,最后回调Activity的onContentChanged方法通知Activity视图已经发生改变。
DecorView作为顶级View,一般情况下它内部会包含一个竖直方向的LinearLayout,在这个LinearLayout里面有上下两个部分,上面是标题栏,下面是内容栏,其中标题栏一般由Activity的Theme样式所决定。在Activity中我们通过setContentView所设置的布局文件其实就是被加到内容栏之中的。
1187237-bc2cbef0a2f7a5fb.png一个比喻总结下Activity Window View三只之间的关系:Activity像一个工匠(控制单元),Window像窗户(承载模型),View像窗花(显示视图)。
如果还有疑问,可以观看我的视频课程:剪不断理还乱的Activity Window View三角关系
网友评论