android wms布局过程,深入理解WMS
8种机械键盘轴体对比本人程序员,要买一个写代码的键盘,请问红轴和茶轴怎么选?窗口(Window)是什么。Android系统中的窗口是屏幕上的一块用于绘制各种UI元素并可以响应应用户输入的一个矩形区域。从原理上来讲,窗口的概念是独自占有一个Surface实例的显示区域。例如Dialog、Activity的界面、壁纸、状态栏以及Toast等都是窗口。《卷I》第8章曾详细介绍了一个Activity通过.
8种机械键盘轴体对比
本人程序员,要买一个写代码的键盘,请问红轴和茶轴怎么选?
窗口(Window)是什么。
Android系统中的窗口是屏幕上的一块用于绘制各种UI元素并可以响应应用户输入的一个矩形区域。从原理上来讲,窗口的概念是独自占有一个Surface实例的显示区域。例如Dialog、Activity的界面、壁纸、状态栏以及Toast等都是窗口。
《卷I》第8章曾详细介绍了一个Activity通过Surface来显示自己的过程:Surface是一块画布,应用可以随心所欲地通过Canvas或者OpenGL在其上作画。
然后通过SurfaceFlinger将多块Surface的内容按照特定的顺序(Z-order)进行混合并输出到FrameBuffer,从而将Android“漂亮的脸蛋”显示给用户。
既然每个窗口都有一块Surface供自己涂鸦,必然需要一个角色对所有窗口的Surface进行协调管理。于是,WMS便应运而生。WMS为所有窗口分配Surface,掌管Surface的显示顺序(Z-order)以及位置尺寸,控制窗口动画,并且还是输入系统的一重要的中转站。
说明一个窗口拥有显示和响应用户输入这两层含义
总结在客户端创建一个窗口的步骤:获取IWindowSession和WMS实例。客户端可以通过IWindowSession向WMS发送请求。
创建并初始化WindowManager.LayoutParams。注意这里是WindowManager下的LayoutParams,它继承自ViewGroup.LayoutParams类,并扩展了一些窗口相关的属性。其中最重要的是type属性。这个属性描述了窗口的类型,而窗口类型正是WMS对多个窗口进行ZOrder排序的依据。
向WMS添加一个窗口令牌(WindowToken)。本章后续将分析窗口令牌的概念,目前读者只要知道,窗口令牌描述了一个显示行为,并且WMS要求每一个窗口必须隶属于某一个显示令牌。
向WMS添加一个窗口。必须在LayoutParams中指明此窗口所隶属于的窗口令牌,否则在某些情况下添加操作会失败。在SampleWindow中,不设置令牌也可成功完成添加操作,因为窗口的类型被设为TYPE_SYSTEM_ALERT,它是系统窗口的一种。而对于系统窗口,WMS会自动为其创建显示令牌,故无需客户端操心。此话题将会在后文进行更具体的讨论。
向WMS申请对窗口进行重新布局(relayout)。所谓的重新布局,就是根据窗口新的属性去调整其Surface相关的属性,或者重新创建一个Surface(例如窗口尺寸变化导致之前的Surface不满足要求)。向WMS添加一个窗口之后,其仅仅是将它在WMS中进行了注册而已。只有经过重新布局之后,窗口才拥有WMS为其分配的画布。有了画布,窗口之后就可以随时进行绘制工作了。
而窗口的绘制过程如下:通过Surface.lock()函数获取可以在其上作画的Canvas实例。
使用Canvas实例进行作画。
通过Surface.unlockCanvasAndPost()函数提交绘制结果。
Android显示系统的三个层次
在图中:第一个层次是UI框架层,其工作为在Surface上绘制UI元素以及响应输入事件。
第二个层次为WMS,其主要工作在于管理Surface的分配、层级顺序等。
第三层为SurfaceFlinger,负责将多个Surface混合并输出。
Android中的窗口概念:屏幕上一块用于绘制各种UI元素并可以响应用户输入的一块矩形区域。从原理上来看,窗口的概念是独自占有一个Surface实例的显示区域。如Dialog、Activity的界面、壁纸、状态栏以及Toast等都是窗口。
上述对窗口的概念性描述,提取出来主要有以下几点信息:用于绘制UI元素
响应用户输入
独自占有一个surface实例
Surface是一块画布,应用通过canvas或者openGL在上面作画
作画后通过SurfaceFlinger将多块Surface的内容按照Z-order进行混合并输出到FrameBuffer,从而将Android的页面显示给用户。
每个窗口都有一块Surface用于显示自己的ui,必然需要一个角色对窗口进行统一管理,这个时候,WMS应运而生。WMS为所有窗口分配Surface,掌管z-order以及位置、尺寸、窗口的进场出场动画,并且还是输入系统的中转站。本文的分析角度:
布局系统:计算管理窗口的位置和层次
动画系统:根据布局系统的计算渲染窗口动画
一个窗口的创建流程大概如下:客户端通过WindowManagerGlobal获取IWindowSession,通过IWindowSession来向WMS发起添加请求。
初始化WindowManager.LayoutParam,指定响应的type,当type大于System级别的时候,不需要token,WMS会创建一个token,而type小于system级别的窗口,是必须要求有token带过来给WMS的。WMS根据这个type来对窗口的z-order进行排序。
向was申请relayout,所谓重新布局,是根据窗口新的属性去调整其Surface的相关属性,或者重新创建一个Surface。向wms添加一个窗口,仅仅是将它在wms中进行注册。只有经过了relayout后,窗口才拥有了wms为其分配的画布,有了画布,窗口才能进行绘制工作。
之后,窗口的绘制过程如下:通过surface.lock()函数获取可以在surface上作画的canvas
使用canvas进行绘图
通过unlockCanvasAndPost提交绘制结果
说到底,Window的本质其实就是一块Surface画布.
于是,根据对Surface的操作类型可以将Android的显示系统分为3个层次。UI框架层,负责View空间的布局、绘制、事件分发、响应
WMS管理窗口Surface的布局与次序
SurfaceFlinger 将WMS维护的窗口Surface按照一定的次序混合后显示到屏幕上。
理解WindowTokenWindowToken的意义
为了搞清楚WindowToken的作用是什么,看一下其位于WindowToken.java中的定义。虽然它没有定义任何函数,但其成员变量的意义却很重要。WindowToken将属于同一个应用组件的窗口组织在了一起。所谓的应用组件可以是Activity、InputMethod、Wallpaper以及Dream。在WMS对窗口的管理过程中,用WindowToken指代一个应用组件。例如在进行窗口ZOrder排序时,属于同一个WindowToken的窗口会被安排在一起,而且在其中定义的一些属性将会影响所有属于此WindowToken的窗口。这些都表明了属于同一个WindowToken的窗口之间的紧密联系。
WindowToken具有令牌的作用,是对应用组件的行为进行规范管理的一个手段。WindowToken由应用组件或其管理者负责向WMS声明并持有。应用组件在需要新的窗口时,必须提供WindowToken以表明自己的身份,并且窗口的类型必须与所持有的WindowToken的类型一致。从上面的代码可以看到,在创建系统类型的窗口时不需要提供一个有效的Token,WMS会隐式地为其声明一个WindowToken,看起来谁都可以添加个系统级的窗口。难道Android为了内部使用方便而置安全于不顾吗?非也,addWindow()函数一开始的mPolicy.checkAddPermission()的目的就是如此。它要求客户端必须拥有SYSTEM_ALERT_WINDOW或INTERNAL_SYSTEM_WINDOW权限才能创建系统类型的窗口。
更多推荐
所有评论(0)