WindowManagerService之Window类型篇

一:背景

    WMS作为窗口管理服务,管理着系统中的所有窗口,窗口的种类有很多:Activity、Dialog、Toast、PopupWindow、StatusBar、NavigationBar、System Alart Window等,那么如此多且繁杂的窗口,是否有比较细致的分类呢?答案是肯定的:有。系统把这些窗口分为了三类:应用窗口、子窗口和系统窗口,下面来看下这三类窗口。

二:窗口类型的定义

窗口类型都是定义在WindowManager的静态内部类LayoutParams中。

2.1 应用窗口

Activity就是典型的应用窗口,应用窗口的定义范围为1-99

public interface WindowManager extends ViewManager {
    public static class LayoutParams extends ViewGroup.LayoutParams implements Parcelable {
        ...
        //应用窗口起始值
        public static final int FIRST_APPLICATION_WINDOW = 1;
        //应用窗口的基础值
        public static final int TYPE_BASE_APPLICATION   = 1;
        //普通应用窗口
        public static final int TYPE_APPLICATION        = 2;
        //应用启动窗口,系统在应用启动前显示的窗口,即StartingWindow
        public static final int TYPE_APPLICATION_STARTING = 3;

        public static final int TYPE_DRAWN_APPLICATION = 4;
        //应用窗口最大值
        public static final int LAST_APPLICATION_WINDOW = 99;
        ...
    }
}

2.2 子窗口

PopupWindow就是典型的子窗口,子窗口不能单独存在,必须依附于其他窗口(非子窗口),子窗口的定义范围为1000-1999

public interface WindowManager extends ViewManager {
    public static class LayoutParams extends ViewGroup.LayoutParams implements Parcelable {
        ...
        //子窗口起始值
        public static final int FIRST_SUB_WINDOW = 1000;
        public static final int TYPE_APPLICATION_PANEL = FIRST_SUB_WINDOW;
        public static final int TYPE_APPLICATION_MEDIA = FIRST_SUB_WINDOW + 1;
        public static final int TYPE_APPLICATION_SUB_PANEL = FIRST_SUB_WINDOW + 2;
        public static final int TYPE_APPLICATION_ATTACHED_DIALOG = FIRST_SUB_WINDOW + 3;
        public static final int TYPE_APPLICATION_MEDIA_OVERLAY  = FIRST_SUB_WINDOW + 4;
        public static final int TYPE_APPLICATION_ABOVE_SUB_PANEL = FIRST_SUB_WINDOW + 5;
        //子窗口最大值
        public static final int LAST_SUB_WINDOW = 1999;
        ...
    }
}

2.3 系统窗口

StatusBar就是典型的系统窗口,系统窗口的定义范围为2000-2999

public interface WindowManager extends ViewManager {
    public static class LayoutParams extends ViewGroup.LayoutParams implements Parcelable {
        ...
        //系统窗口起始值
        public static final int FIRST_SYSTEM_WINDOW     = 2000;
        //StatusBar
        public static final int TYPE_STATUS_BAR         = FIRST_SYSTEM_WINDOW;
        //SearchBar
        public static final int TYPE_SEARCH_BAR         = FIRST_SYSTEM_WINDOW+1;
        //通话窗口
        public static final int TYPE_PHONE              = FIRST_SYSTEM_WINDOW+2;
        //系统警告窗口
        public static final int TYPE_SYSTEM_ALERT       = FIRST_SYSTEM_WINDOW+3;
        //锁屏
        public static final int TYPE_KEYGUARD           = FIRST_SYSTEM_WINDOW+4;
        //Toast
        public static final int TYPE_TOAST              = FIRST_SYSTEM_WINDOW+5;
        ...
        public static final int TYPE_STATUS_BAR_ADDITIONAL = FIRST_SYSTEM_WINDOW + 41;
        //系统窗口最大值
        public static final int LAST_SYSTEM_WINDOW      = 2999;
        ...
    }
}

三:小结

3.1 窗口类型的定义除了区分不同种类窗口外,还有什么用?

    窗口类型(即Type)的值和窗口显示息息相关。SurfaceFlinger显示时,会先对所有窗口进行排序,不同的窗口是以平行于手机屏幕的方式叠加显示的,优先级越高的窗口就离手机屏幕越远(非物理上的远近,只是借用这个概念),Type就影响了窗口的优先级,一般情况下Type越小,窗口的优先级越低,就会被更多的窗口覆盖。

Android 系统中,`WindowManagerService`(简称 WMS)负责管理所有窗口的生命周期、布局、显示状态等核心功能。`postDelayed` 是 Android 中常见的用于延迟执行任务的方法,它通常用于避免某些操作立即执行,而是等待一段时间后执行,以确保系统状态的稳定。 在 WMS 中,`postDelayed` 常用于处理窗口冻结(Window Freeze)的超时机制。当系统进入休眠、屏幕旋转或窗口动画等状态时,可能会临时冻结窗口内容以避免视觉混乱或资源浪费。如果在设定的时间内没有完成解冻操作,则触发超时处理,强制解冻以恢复正常的 UI 渲染流程。 `postDelayed` 的调用通常与 `WINDOW_FREEZE_TIMEOUT_DURATION` 配合使用,后者定义了窗口冻结的最大等待时间。在源码中,该常量通常定义为 5000 毫秒(即 5 秒),用于确保系统在合理时间内恢复窗口绘制状态[^2]。 以下是一个典型的冻结超时处理逻辑示例: ```java mH.postDelayed(mStopFreezingScreenRunnable, WINDOW_FREEZE_TIMEOUT_DURATION); ``` 其中 `mStopFreezingScreenRunnable` 是一个 `Runnable` 对象,用于在超时后执行解冻操作。这种机制确保即使某些操作未能及时完成,系统也不会永久冻结屏幕,从而避免 ANR(Application Not Responding)问题。 在窗口冻结过程中,WMS 会将窗口的绘制状态设置为特定的标志,如 `DRAW_PENDING` 或 `READY_TO_SHOW`,并在绘制完成后更新状态。如果在 `WINDOW_FREEZE_TIMEOUT_DURATION` 时间内未完成绘制,则通过 `postDelayed` 提交的 `Runnable` 会强制清除冻结状态,恢复正常绘制流程[^2]。 ### 窗口状态与冻结机制的关系 窗口状态的管理是 WMS 的核心职责之一。冻结操作通常发生在屏幕旋转、多任务切换等场景中。冻结期间,系统会暂停窗口的绘制更新,以避免显示不完整或混乱的内容。一旦冻结超时,系统会强制解冻并恢复绘制,以防止长时间黑屏或 UI 卡顿。 ### 示例代码片段 ```java private final Runnable mStopFreezingScreenRunnable = new Runnable() { @Override public void run() { synchronized (mService.getWindowManagerLock()) { stopFreezingDisplayLocked(); } } }; ``` 在 `stopFreezingDisplayLocked()` 方法中,WMS 会清除冻结标志,并通知相关组件恢复绘制操作。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值