Activity Window View 三者之间的关系

问题引入

  • 代码写久了发现有些问题,到底那些view时怎么显示在屏幕上的,怎么显示在window上的,还有我们刚开始学习android时候,每次新建一个Activity,在onCreate方法中都会使用setContentView这个方法传递一个布局,它又是怎么显示到屏幕上的呢?

首先Actiivity就是创建了一个Window,Activity实际就是Context的一个子类,Context是一个抽象类。。(Activity在创建的时候就创建了一个Window,同时也创建一个decorview)

  • DecorView是什么?

DecorView是Activity中的顶级View,内部包含标题栏和内部栏

在第二部分在事件传递初始时候,单击事件从Activity传递到Window再到传递给DecorView,再由DecorView传递给我们的View,我们来学习一下它们三者之间的关系。

  • 按钮是怎么显示在Activity上的内,是怎么绘制在手机屏幕的呢?

答案:通过Window这个类,在Activity创建的时候会创建一个Window,Window通过viewroot将decorview和view添加在window上。

我么在创建Activity的时候,系统会自动帮我们创建一个decorview,decorview是依赖viewroot将自己添加到window上。

Window的基本介绍

Android所有的视图都是通过Window来呈现的,不管是Activity,Dialog还是Toast,它们的视图都是附加在Window上的,因此Window是View的实际操控者。

如何使用WindowManager添加一个Window,过程代码是什么样的。

注意这其中有一个WindowManager.LayoutParams(),()里面的参数包括一个flag和一个type,flag(flag参数表示window的属性),分那些种类型,代表什么含义,type分那几种(type参数表示window的类型),表示什么含义。

Window的创建过程

前言

Window一共分为几种基本类型:应用Window(Activity),子Window(Dialog),系统Window(toast)
有视图的地方就有Window,因此Activity Dialog Toast等视图都应对应着一个Window,有视图的地方就有Window,PopUpWindow也应该对应着Window。

Window的创建过程,Window事抽象类,它的实现类是PhoneWindow。创建一个Window是一个很简单的事,只需要通过WindowManager来完成,其实Activity的设置视图方法setContentView在底层也是通过Window来完成的,查看源码发现调用的事phoneWindow的setContentView

分上面三种Window分别讲解Window的创建过程

Activity的Window创建过程

第一步:在创建Activity实例的时候,系统就会创建Activity所属的Window对象,并为Window
对象设置回调Callback接口(留下悬念注意这个接口什么时候调用哈),创建的方法是PolicyManager的makeNewWindow 策略模式创建出来的Window

第二步:Window创建完成后,分析Activity的视图是怎么附属到Window上的。看代码,这时候的代码只有一处调用setContentView,查看setContentView,发现里面是调用getWindow.setContentView,接下来查看PhoneWindow的setContentView方法

第三步:分析PhoneWindow的setContentView,内部首先判断是否有DecorView,如果没有DecorView,则去创建DecorView,DecorView包括标题栏和内部栏。

第四步:有了DecorView,将View(也就是将Activity中的视图)添加到DecorView的mContentParent中。到此为止,Activity的布局已经添加到了DecorView中了

第五步:第一步中Activity为Window设置了回调函数,是时候调用这些回调函数了,一旦确定了布局文件已经添加到了DecorView的mContentParent中,就需要通知Activity做一些处理。

第六步:条件都具备后,布局文件已经成功添加到了DecorView的mContentParent中,是时候添加到Window中了,在ActivityThread的handleResumeActivity方法中,会调用Activity的onResume方法,接着会调用Activity的makeVisable(),在这个方法中DecorView真正的完成了添加和显示两个过程,到这里Activity视图才被用户看到。

++(在这里也明白了Activity的生命周期,在onResume执行后才真的能被看到)++

Dialog的Window创建过程

Dialog的Window创建过程基本与Activity相同

简单说一下:

第一步:创建Window,不过是在Dialog的函数中完成的,实际方法与Activity中的相同,Policy.makeNewWindow

第二步:仍然是使用setContentView初始化DevorView,然后将布局文件也就是Dialog的视图添加到DetorView中

第三步:将DetorView添加到Window中显示,dialog调用show方法的时候,会通过WindowManager.addView添加到Window中

++(在这里我也终于想明白了为什么自定义Dialog的时候调用一个setContentView,而在自定义RowView的时候使用 LayoutInflater.from(mContext).inflate就可以)++

注意点:普通的dialog,创建的时候,必须采用Activity的Context,如果采用Application的Context会报错,也不是没有解决办法,改变Window的Type类型,为系统类型,然后不要忘了添加权限

dialog.getWindow().setType(LayoutParams.TYPE_SYSTEM_ERROR);
权限文件中添加SYSTEM_ALERT_WINDOW
(上面事什么原因有没有考虑过,为什么Dialog使用Application的Context会报错,报错显示缺少token,token一般只有在Activity中有,无法获取到token,而系统Window不需要token,也能正常显示视图弹出框,就有了上面的解决办法)

Toast的Window创建过程

PopWindow的Window创建过程

Window的三种类型上面已经提到过应用Window(Activity),子Window(Dialog)系统Window(Toast),但是对于PopUpWindow,菜单也同样是视图,有视图的地方就有Window,也同样会创建Window

Activity,Window,View三者功能总结:

  • Activity就是控制单元(控制Window,同时也依赖Window)

  • Window是承载模型(承载view和decorview)

  • view是显示视图(通过viewroot显示到window上,decorview是依赖viewroot显示到window上,创建activity的时候就创建了decorview,setContentView将我们自己定义的view建立到decorview上)

联想:

开发商卖房子的装修风格,符合可以用,可以改,不符合都不用。

猜你喜欢

转载自blog.csdn.net/xgangzai/article/details/81390630