Android:窗口管理器WindowManager

导言
本篇文章主要是对Android中与窗口(Window)有关的知识的介绍,主要涉及到的有:
- Window
- WindowManager
- WindowManagerService
主要是为了更进一步地向下地深入Android屏幕渲染的知识(虽然窗口可能并算不上)。
窗口(Window)
Q:什么是窗口
实际上Android上的窗口指的并不是具体的手机窗口而是一个抽象的概念,它本质上也是一个View,我会把窗口理解成一组有关联的View。
与ActivityManager与ActivityManagerService的关系类似,WindowManager中方法的实现也是通过远程调用WindowManagerService实现的:

窗口的属性
窗口的类型
Window的类型大体来分有三种,我们可以在源文件中找到具体的对应:

-
- 应用程序窗口:最常见的,顶层应用的显示窗口
-
- 子窗口:需要依附在其他窗口的窗口
-
- 系统窗口: Toast,系统输入法窗口,系统错误窗口等
另外,每种窗口还有其对应的TYPE值,这个值主要是用来确定窗口的显示层次的,应用程序窗口的TYPE值在1-99范围内,子窗口在1000-1999,系统窗口在2000-2999。至于这个TYPE值会如何影响显示层次呢?这里我们可以简单的将这个TYPE值看做是一个z轴的坐标值,也就是垂直于手机屏幕的距离,数值越大,其离手机屏幕就越远,那么显示的优先级也会越高。
当然,实际的情况比这要复杂,会涉及到一些加权的计算,这里我们先简单这样理解即可。
窗口的标志
窗口的标志决定了窗口的一些响应特性,这里直接给出一些常用的flag理解一下:
| Flag | 描述 |
|---|---|
| FLAG_ALLOW_LOCK_WHILE_SCREEN_ON | 只要窗口可见,就允许在开启状态的屏幕上锁屏 |
| FLAG_NOT_FOCUSABLE | 窗口不能获得输入焦点,在设置该标志的同时也会将FLAG_NOT_TOUCH_MODAL设置 |
| FLAG_NOT_TOUCHABLE | 窗口不接受任何触摸事件 |
| FLAG_NOT_TOUCH_MODAL | 将该窗口区域之外的触摸事件传递给其他的Window,而自己只会处理窗口区域内的触摸事件 |
| FLAG_KEEP_SCREEN | 只要窗口可见,就会一直保持长亮 |
| FLAG_LAYOUT_NO_LIMITS | 允许窗口显示在手机屏幕之外 |
| … |
Window的具体实现类PhoneWindow
这个PhoneWindow我们应该在Activity的setContentView方法中有提及到,这里再简单回顾一下:
public void setContentView(@LayoutRes int layoutResID) {
initViewTreeOwners();
getDelegate().setContentView(layoutResID);
}
//Activity.java中
public void setContentView(View view, ViewGroup.LayoutParams params) {
getWindow().setContentView(view, params);
initWindowDecorActionBar();
}
当我们调用Activity的setContentView方法时首先会根据后面传入的xml布局文件初始化整棵视图树,之后会获取到Activity自身对应的Window对象,也就是描述Activity该如何显示的一个View,之后再调用该Window的setContentView方法,那这个Window对象是在何处被初始化的呢?答案是在Activity的attach方法中,该方法是在ActivityThread中被调用的:
final void attach(...) {
attachBaseContext(context);
mFragments.attachHost(null /*parent*/);
mWindow = new PhoneWindow(this, window, activityConfigCallback);
......
mWindow.setWindowManager(
(WindowManager)context.getSystemService(Context.WINDOW_SERVICE),
mToken, mComponent.flattenToString(),
(info.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0);
}
可以清楚的看到此处将Activity对应的PhoneWindow对象实例创建了出来,并将这个对象与一个WindowManager对象绑定起来,所以说上面Activity调用的setContentView最终是由这个PhoneWindow对象实例来完成的,最终就会在PhoneWindow中安装一个DecorView,DecorView作为整个PhoneWindow中的第一个View(实际上的根View),并把xml中的内容填充进DecorView的内容部分。
WindowManager(窗口管理者)
WindowManager接口
接下来我们从源码角度先分析一下WindowManager:
public interface WindowManager extends ViewManager
可以看到WindowManager本质上是一个继承了ViewManager接口的一个接口,因为ViewManager比较简单,我们先来看ViewManager接口:
public interface ViewManager
{
public void

本文详细解析了Android中的窗口概念、WindowManager的作用,涉及Window类型、属性、标志,以及PhoneWindow和WindowManagerImpl的实现。重点介绍了ViewRootImpl在窗口管理中的角色,以及如何在子线程更新UI的特殊情况。
6745

被折叠的 条评论
为什么被折叠?



