在前一个系列文章中,我们从个体的角度来分析了Android应用程序窗口的实现框架。事实上,如果我们从整体的角度来看,Android应用程序窗口的 实现要更复杂,因为它们的类型和作用不同,且会相互影响。在Android系统中,对系统中的所有窗口进行管理是窗口管理服务 WindowManagerService的职责。在本文中,我们就将简要介绍WindowManagerService的职能以及制定学习计划。

我们知道,在Android系统中,同一时刻,只有一个Activity窗口是激活的,但是,对于WindowManagerService服务来说,这 并不意味着它每次只需要管理一个Activity窗口,例如,在两个Activity窗口的切换过程中,前后两个Activity窗口实际上都是可见的。 即使在只有一个Activity窗口是可见的时候,WindowManagerService服务仍然需要同时管理着多个窗口,这是因为可见的 Activity窗口可能还会被设置了壁纸窗口(Wallpaper Winodw)或者弹出了子窗口(Sub Window),以及可能会出现状态栏(Status Bar)以及输入法窗口(Input Method Window),如图1所示。

图1 Activity窗口及其子窗口、壁纸窗口、输入法窗口和状态栏的位置结构

因此,WindowManagerService服务是不可以假设同一时刻它只需要管理一个窗口的,它需要通过各个窗口在屏幕上的位置以及大小来决定哪些窗口需要显示的以及要显在哪里,这实际上就是要计算出各个窗口的可见区域。

从前面Android系统Surface机制的SurfaceFlinger服务渲染应用程序UI的过程分析一 文可以知道,SurfaceFlinger服务在渲染整个屏幕的UI的时候,会对各个窗品的可见性进行计算,因 此,WindowManagerService服务只要将它所管理的各个窗品的位置以及大小告诉SurfaceFlinger服务,后者可以帮帮它计算出 各个窗口的可见区域了。注意,这里,这里所说的窗口位置包括窗口在X、Y和Z轴的位置。

WindowManagerService服务大致按照以下方式来控制哪些窗口需要显示的以及要显在哪里:

1. 每一个Activity窗口的大小都等于屏幕的大小,因此,只要对每一个Activity窗口设置一个不同的Z轴位置,然后就可以使得位于最上面的,即当前被激活的Activity窗口,才是可见的。

2. 每一个子窗口的Z轴位置都比它的父窗口大,但是大小要比父窗口小,这时候Activity窗口及其所弹出的子窗口都可以同时显示出来。

3. 对于非全屏Activity窗口来说,它会在屏幕的上方留出一块区域,用来显示状态栏。这块留出来的区域称对于屏幕来说,称为装饰区(decoration),而对于Activity窗口来说,称为内容边衬区(Content Inset)。

4. 输入法窗口只有在需要的时候才会出现,它同样是出现在屏幕的装饰区或者说Activity窗口的内容边衬区的。

5. 对于壁纸窗口,它出现需要壁纸的Activity窗口的下方,这时候要求Activity窗口是半透明的,这样就可以将它后面的壁纸窗口一同显示出来。

6. 两个Activity窗口在切换过程,实际上就是前一个窗口显示退出动画而后一个窗口显示开始动画的过程,而在动画的显示过程,窗口的大小会有一个变化的 过程,这样就导致前后两个Activity窗口的大小不再都等于屏幕的大小,因而它们就有可能同时都处于可见的状态。事实上,Activity窗口的切换 过程是相当复杂的,因为即将要显示的Activity窗口可能还会被设置一个启动窗口(Starting Window)。一个被设置了启动窗口的Activity窗口要等到它的启动窗口显示了之后才可以显示出来。

从以上六点就可以看出,窗口在X、Y和Z轴的位置及其大小的计算非常重要,它们共同决定了一个窗口是否是整体可见的,还是部分可见的,或者整体不可见 的。在Android系统中,WindowManagerService服务是通过一个实现了WindowManagerPolicy接口的策略类来计算 一个窗口的位置和大小的。例如,在Phone平台上,这个策略类就是PhoneWindowManager。这样做的好处就是对于不同的平台实现不同的策 略类来达到不同的窗口控制模式。

从上面的描述就可以看出,WindowManagerService服务除了要与Activity窗口所运行在的应用程序进程打交道之外,还需要与SurfaceFlinger服务以及窗口管理策略类PhoneWindowManager交互,如图2所示。

图2 WindowManagerService服务与Activity窗口、SurfaceFlinger服务、PhoneWindowManager策略的关系图

在前面Android应用程序窗口(Activity)实现框架简要介绍和学习计划的 一系列文章中,我们已经分析过应用程序进程与WindowManagerService服务之间的交互过程了,因此,在这一系列文章中,我们就将主要分析 WindowManagerService服务的实现,以及它与SurfaceFlinger服务、PhoneWindowManager策略类的交互过 程。

从总体上来看,WindowManagerService服务的实现是相当复杂的,例如,WindowManagerService类的核心成员函数 performLayoutAndPlaceSurfacesLockedInner的代码有1200+行,比600-行代码的ViewRoot类的核心 成员函数performTraversals还要恐怖。不过,WindowManagerService服务实现的复杂性是在预料之中的,毕竟它要管理的 整个系统所有窗口的UI,而在任何一个系统中,窗口管理子系统都是极其复杂的。基于上述理由,采用硬碰硬的方式来分析 WindowManagerService服务的实现是以卵击石,因此,这个系列的文章将对WindowManagerService服务进行分拆,然后 再逐个击破,这是算法中的分而治之思想是一致的。

具体来说,我们将按照以下几个情景来分析WindowManagerService服务的实现:

1. 窗口大小和位置(X轴和Y轴)的计算过程

2. 窗口的组织方式

3. 输入法窗口的调整过程

4. 壁纸窗口的调整过程

5. 窗口Z轴位置的计算和调整过程

6. Activity窗口的启动窗口的显示过程

7. Activity窗口的切换过程

8.Activity窗口的动画显示过程

再次地,由于WindowManagerService服务的实现实在是太复杂,因此上述八个情景可能还不足于说明 WindowManagerService服务的实现。如果出现这种情况,我们在分析的过程中会进行相应的调整。相信对 WindowManagerService服务的实现进行分而治之的分析后,我们就可以对Android系统的UI架构有一个深刻的理解!敬请关注接下来 的文章!

老罗的新浪微博:http://weibo.com/shengyangluo,欢迎关注!

Android窗口管理服务WindowManagerService的简要介绍和学习计划的更多相关文章

  1. Android窗口管理服务WindowManagerService显示窗口动画的原理分析

    文章转载至CSDN社区罗升阳的安卓之旅,原文地址:http://blog.csdn.net/luoshengyang/article/details/8611754 在前一文中,我们分析了Activi ...

  2. Android窗口管理服务WindowManagerService显示Activity组件的启动窗口(Starting Window)的过程分析

    文章转载至CSDN社区罗升阳的安卓之旅,原文地址:http://blog.csdn.net/luoshengyang/article/details/8577789 在Android系统中,Activ ...

  3. Android窗口管理服务WindowManagerService计算窗口Z轴位置的过程分析

    文章转载至CSDN社区罗升阳的安卓之旅,原文地址:http://blog.csdn.net/luoshengyang/article/details/8570428 通过前面几篇文章的学习,我们知道了 ...

  4. Android窗口管理服务WindowManagerService切换Activity窗口(App Transition)的过程分析

    文章转载至CSDN社区罗升阳的安卓之旅,原文地址:http://blog.csdn.net/luoshengyang/article/details/8596449 在Android系统中,同一时刻只 ...

  5. Android窗口管理服务WindowManagerService对壁纸窗口(Wallpaper Window)的管理分析

    文章转载至CSDN社区罗升阳的安卓之旅,原文地址:http://blog.csdn.net/luoshengyang/article/details/8550820 Android系统中,壁纸窗口和输 ...

  6. Android窗口管理服务WindowManagerService对输入法窗口(Input Method Window)的管理分析

    文章转载至CSDN社区罗升阳的安卓之旅,原文地址:http://blog.csdn.net/luoshengyang/article/details/8526644 在Android系统中,输入法窗口 ...

  7. Android应用程序组件Content Provider简要介绍和学习计划

    文章转载至CSDN社区罗升阳的安卓之旅,原文地址:http://blog.csdn.net/luoshengyang/article/details/6946067 在Android系统中,Conte ...

  8. Android窗口管理服务WindowManagerService对窗口的组织方式分析

    文章转载至CSDN社区罗升阳的安卓之旅,原文地址:http://blog.csdn.net/luoshengyang/article/details/8498908 我们知道,在Android系统中, ...

  9. Android窗口管理服务WindowManagerService计算Activity窗口大小的过程分析

    来自http://blog.csdn.net/luoshengyang/article/details/8479101 在Android系统中,Activity窗口的大小是由WindowManager ...

随机推荐

  1. 导致flash屏幕重绘的几种方式及避免重绘的方法

    导致屏幕重绘的几种原因: 1.最常见的是情况就是舞台上的可视组件在形状.位置.状态(alpha, scale…)发生改变的时候会触发Flash Player 的重绘. 2.当一个DisplayObje ...

  2. Struts1——从BeanUtils看struts的实现原理2

        上一篇博客中我们简单的介绍了BeanUtils的使用.以及其最主要的原理,今天我们进一步的理解这个类在Struts1中的使用.     首先我们先回想一下搭建一个简单的基于Struts1框架的 ...

  3. [Cycle.js] From toy DOM Driver to real DOM Driver

    This lessons shows how we are able to easily swap our toy DOM Driver with the actual Cycle.js DOM Dr ...

  4. Linux各个目录的作用

      /binbin是binary的缩写.这个目录沿袭了UNIX系统的结构,存放着使用者最经常使用的命令.例如cp.ls.cat,等等./boot这里存放的是启动Linux时使用的一些核心文件./dev ...

  5. [core java学习笔记][第十一章异常断言日志调试]

    第11章 异常,断言,日志,调试 处理错误 捕获异常 使用异常机制的技巧 使用断言 日志 测试技巧 GUI程序排错技巧 使用调试器 11.1 处理错误 11.1.1异常分类 都继承自Throwable ...

  6. css_day5

  7. ToString()和Convert.ToString()的区别

    ToString()和Convert.ToString()的区别 一般情况下,这两种方法都可以通用,但是当返回的数据类型中有可能出现null值时如果调用ToString方法了,就会返回NullRefe ...

  8. Asp.net开发常用的51个非常实用的代码

    1.弹出对话框.点击转向指定页面 Code: Response.Write("<script>window.alert('该会员没有提交申请,请重新提交!')</scrip ...

  9. C#中方法Show.和ShowDialog的使用区别

    show()是非模式窗体. showDialog()是模式窗体. 如果这个时候用Show的话,则会发生的事情是,打开子窗体的同时主窗体又显示出来,而使用ShowDialog()的时候主要当子窗体关闭的 ...

  10. 二维计算几何基础题目泛做(SYX第一轮)

    题目1: POJ 2318 TOYS 题目大意: 给一个有n个挡板的盒子,从左到右空格编号为0...n.有好多玩具,问每个玩具在哪个空格里面. 算法讨论: 直接叉积判断就可以.注意在盒子的边界上面也算 ...