深入浅出安卓WMS

414 阅读3分钟

深入浅出讲解安卓WMS(Window Manager Service)

WMS(Window Manager Service,窗口管理服务)是Android系统中负责管理所有窗口(Window)的核心服务。它决定了哪个窗口显示在最前面、如何布局、怎样处理触摸事件,就像是一个窗口调度员


一、WMS是干什么的?

想象你的手机屏幕是一个大舞台,WMS就是舞台导演,负责:

  1. 窗口的显示与隐藏(比如:弹窗、Activity、输入法、状态栏)
  2. 窗口的层级(Z-order)(谁在上面,谁在下面)
  3. 窗口的尺寸和位置(比如分屏、悬浮窗)
  4. 触摸事件的分发(点哪里?交给谁处理?)
  5. 动画和过渡效果(比如Activity切换动画)

二、WMS管理哪些窗口?

Android的窗口主要分为几类:

窗口类型示例特点
应用窗口(Application Window)Activity、Dialog普通App的界面
子窗口(Sub Window)PopupWindow、菜单必须依附于某个父窗口
系统窗口(System Window)状态栏、Toast、输入法全局显示,不受Activity限制
悬浮窗(Floating Window)悬浮球、小窗模式可以叠加在其他窗口上

三、WMS的核心工作原理

1. 窗口的添加与移除

  • 添加窗口:当Activity启动时,WMS会:
    • 分配一个Surface(绘制的画布)
    • 计算窗口的位置和大小
    • 决定它的Z轴顺序(谁盖住谁?)
  • 移除窗口:当Activity关闭时,WMS会:
    • 释放对应的Surface
    • 调整其他窗口的布局(比如输入法退出后,界面要重新调整)

2. 窗口的层级(Z-order)

WMS用Z-order决定窗口的显示顺序,比如:

  • 系统窗口(如状态栏) 通常在最顶层(Z轴值最大)
  • 普通Activity窗口 在中间层
  • 壁纸(Wallpaper) 在最底层

3. 触摸事件的分发

当你点击屏幕:

  1. InputManager 收到触摸事件
  2. WMS 根据窗口的Z-order,找到最顶层的窗口
  3. WMS 把事件交给对应的窗口处理(比如Activity或Dialog)

4. 窗口动画

Activity切换、Dialog弹出时的动画,也是由WMS控制的:

  • WMS 告诉SurfaceFlinger(负责合成的系统服务)如何做动画
  • 比如:平移、缩放、淡入淡出

四、WMS与其他服务的关系

WMS不是孤立的,它和其他系统服务紧密配合:

服务交互方式作用
AMS(Activity Manager)通过Binder通信AMS告诉WMS哪个Activity要显示
SurfaceFlinger通过Surface控制WMS管理窗口的绘制缓冲区
InputManager事件传递WMS决定触摸事件交给谁

五、开发者需要关注的WMS问题

1. 窗口类型的选择

  • 普通Activity用 TYPE_APPLICATION
  • 全局弹窗用 TYPE_APPLICATION_OVERLAY(需要悬浮窗权限)
  • 系统Alert用 TYPE_SYSTEM_ALERT(已废弃,Android 8.0+受限)

2. 窗口层级调整

WindowManager.LayoutParams params = getWindow().getAttributes();
params.type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
params.flags |= WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
getWindow().setAttributes(params);

3. 悬浮窗权限

Android 8.0+必须申请:

<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />

并在代码中动态请求:

if (!Settings.canDrawOverlays(this)) {
    Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION);
    startActivity(intent);
}

4. 窗口焦点问题

  • 如果弹窗抢了焦点,可以加 FLAG_NOT_FOCUSABLE
  • 输入法弹出时,WMS会自动调整窗口,避免被遮挡

六、WMS的常见问题

1. 为什么我的Dialog不显示?

  • 可能没设置正确的 WindowManager.LayoutParams
  • 可能缺少悬浮窗权限(Android 8.0+)

2. 为什么点击事件穿透了?

  • 检查窗口的 FLAG_NOT_TOUCHABLEFLAG_NOT_FOCUSABLE
  • 可能是Z-order设置错误,导致事件被上层窗口拦截

3. 为什么Activity切换卡顿?

  • WMS在计算窗口动画和布局
  • 可能是 onCreate() 太耗时,导致WMS等待

总结

  • WMS是Android的窗口大管家,负责管理所有窗口的显示、层级、触摸事件。
  • 窗口类型决定它的行为(普通窗口、系统窗口、悬浮窗)。
  • Z-order决定谁在上面,谁在下面。
  • 触摸事件由WMS决定分发给哪个窗口。
  • 开发者要注意窗口权限、层级、焦点,避免出现显示或交互问题。

理解WMS,能让你更好地处理UI显示、弹窗、触摸事件等问题! 🚀