Android WindowManager:窗口管理、事件分发与底层通信
一、WindowManager 的核心功能:窗口生命周期管理
WindowManager 是一个位于应用进程的接口,它是开发者与 Android 窗口管理系统进行交互的唯一入口。它负责管理窗口的整个生命周期:从创建到更新再到销毁。
1. 添加窗口(addView)
- 功能:
addView方法用于将一个View添加到屏幕上,创建一个新的窗口。 - 场景:创建悬浮窗(Floating Window)、自定义
Toast或Dialog。 - 底层原理:
WindowManager通过 Binder IPC 向SystemServer进程中的WindowManagerService(WMS)发送一个创建窗口的请求。WMS 负责在系统层面创建窗口,并分配一个Surface作为绘制的画布。
2. 更新窗口(updateViewLayout)
- 功能:
updateViewLayout方法用于动态修改窗口的布局参数(LayoutParams)。 - 场景:拖动悬浮窗、动态调整窗口大小或透明度。
- 底层原理:
WindowManager会将修改后的LayoutParams对象发送给 WMS。WMS 随后会根据新的参数调整窗口的位置和尺寸,并触发相应的重绘。
3. 删除窗口(removeView)
- 功能:
removeView方法用于将一个View从屏幕上移除,并销毁其关联的窗口。 - 场景:关闭悬浮窗、页面销毁时清理残留
View。 - 底层原理:
WindowManager向 WMS 发送一个销毁窗口的请求。WMS 接收到请求后,会销毁窗口、回收其Surface,并释放所有相关资源。
二、窗口参数(LayoutParams):窗口行为的配置器
WindowManager.LayoutParams 是一个配置对象,它定义了窗口的行为、外观和位置。
-
type:决定窗口在屏幕上的层级(Z-order)。TYPE_APPLICATION_OVERLAY:用于悬浮窗,其层级高于应用窗口。TYPE_TOAST:用于系统提示,层级高于悬浮窗。
-
flags:控制窗口的特性。FLAG_NOT_FOCUSABLE:窗口不获取焦点,可以实现点击穿透效果。FLAG_LAYOUT_NO_LIMITS:允许窗口突破屏幕边界进行绘制。
-
gravity:定义窗口在屏幕上的对齐方式。
三、悬浮窗开发与陷阱
悬浮窗是 WindowManager 最典型的应用场景之一,但其开发也充满了陷阱。
- 权限问题:创建悬浮窗需要
android.permission.SYSTEM_ALERT_WINDOW权限。在 Android 6.0 及以上版本,该权限是危险权限,需要动态申请,并引导用户到设置页面手动开启。 - 内存泄漏:悬浮窗的生命周期独立于
Activity。如果悬浮窗没有被及时移除,它会持有Activity或Context的引用,导致内存泄漏。最佳实践是在Activity的onDestroy()方法中调用windowManager.removeView()。 - 层级问题:如果悬浮窗的
type设置不当,可能会被其他窗口覆盖。