什么是Window
窗口即是屏幕上的一块用于绘制各种UI元素并可以响应用户输入的一个矩形区域。从原理上讲,窗口的概念是独自占有一个Surface实例的显示区域(我们在屏幕上看到的图形都需要绘制在Surface上);
Window是个抽象类其实现类为PhoneWindow。
LayoutParams.type
| value | type | decs | |
|---|---|---|---|
| 0 - 999 | 应用程序窗口 | 一般情况下应用显示的窗口就是此类型 | |
| 1000 - 1999 | 子窗口,也可以叫普通弹窗 | Dialog 或 PopWindow 等显示的类型,type 值较高,会显示在应用程序窗口之上 | 普通弹窗显示需要一个依附的 window ,弹窗的显示需要 token 非空,token 来自依附的 window |
| 2000 - 2999 | 系统级窗口 | 最高等级的窗口,一般作为系统自身应用使用,例如来电、下拉屏的显示等 | 要求应用程序安装于 /system/app,签名需要使用系统签名,2038 特殊值除外 特殊值 2038,即 TYPE_APPLICATION_OVERLAY,该值是唯一不用作为系统应用就可以使用的系统级窗口。如果有需要遮住 0 - 1999 的,使用即可 |
App resume流程
当Activity.onResume()被调用之后,客户端会与WMS进行通信将我们的布局显示在屏幕上;
在这个过程中,涉及到一个概念:mDrawState
| name | value | desc |
|---|---|---|
| NO_SURFACE | 0 | mDrawState在定义的时候,默认 = 0,即NO_SURFACE 当一个窗口刚刚被WMS执行addWindow()方法创建的时候,WindowStateAnimator在WindowState的构造函数中一起被创建,在relayoutWindow之前,窗口是没有Surface的,所以不可能被显示出来,此时状态就是NO_SURFACE; |
| DRAW_PENDING | 1 | 客户端调用了relayoutWindow(),这个时候通过WindowManagerServcice的createSurfaceControl()创建了SurfaceControl,然后为窗口创建了一块空白的Surface,此时需要客户端在Surface上作画,但由于Surface为空白状态,所以还是不能显示出; |
| COMMIT_DRAW_PENDING | 2 | 在获取到要绘制的Surface时,ViewRootImpl就通过Canvas在Surface上进行绘制,绘制完成之后会调用Session的finishDrawing()方法,调用到WMS的finishDrawingWindow()方法; |
| READY_TO_SHOW | 3 | 在WMS内部的findDrawingWindow()在设置完状态后,接着执行了mWindowPlacerLocked.requestTraversal()来请求刷新窗口,跟着调用关系,最终会调用到DIsplayContent的applySurfaceChangesTransaction()方法 |
| HAS_DRAWN | 4 | 最后阶段会执行WindowState的performShowLocked()显示画面 |
在WMS中,我们可以通过一个状态值mDrawState来划分几个阶段:
NO_SURFACE
- 客户端通知WMS创建一个窗口,并添加到WindowToken,即addToDisplayAsUser阶段;
- 客户端通知WMS创建Surface,并计算窗口尺寸大小,即relayoutWindow阶段;
DRAW_PENDING
- 客户端获取到WMS计算的窗口大小后,进一步测量该窗口下View的宽度和高度,即performMeasure阶段;
- 客户端确定该窗口下View的尺寸和位置,即performLayout阶段;
- 确定好View的尺寸大小位置之后,便对View进行绘制,即performDraw阶段;
COMMIT_DRAW_PENDING
- 通知WMS,客户端已经完成绘制,即reportDrawFinished阶段;
READY_TO_SHOW
- WMS接收到客户端通知后,紧接着向WMS Animator发送通知,即commitFinishDrawingLocked阶段;
HAS_DRAWN
- WMS进行系统窗口的状态刷新以及动画处理,并最终将Surface显示出来,即performShowLocked阶段;
Resume 细节
handleResumeActivity
add View
add Window
relayout
relayout完成之后,WMS端就为Client创建好了对应的SurfaceControl实例,Client端需要中SurfaceControl中获取对应的Surface作为Canvas进行绘制;