Skip to content
阅读进度

IMS 怎样把一次触摸送到按钮?WMS 在哪里参与? ​

返回 Framework 与系统服务 目录

标准回答 ​

IMS 这里指 InputManagerService,它协调 Android 的输入设备与输入系统。触摸信号先由驱动上报,EventHub 读取底层事件,InputReader 结合设备配置转换成 Android 输入事件,再交给 InputDispatcher 决定如何分发。

InputDispatcher 根据显示区域、可触摸窗口、坐标、焦点和系统策略等信息选择目标。触摸通常看坐标命中和当前手势归属,按键通常与焦点有关,不能简单说所有事件都发给最上面或当前焦点窗口。窗口信息由窗口与显示相关系统链路协调提供,WMS 是其中的重要参与者。

事件通过输入通道到应用侧,由 ViewRootImpl 等接收,再进入 Activity、DecorView 和 View 树的分发链路。ViewGroup 决定是否拦截,子 View 的监听器与 onTouchEvent 继续处理;符合点击条件时才触发 onClick。系统的 InputDispatcher 不会直接查找一个按钮并调用它的 onClick。

因此,点了没反应要分层查:底层有没有事件,系统选中了哪个显示和窗口,应用是否及时接收,View 是否拦截或消费,以及主线程是否阻塞。应用长时间不能完成输入处理,可能触发输入相关 ANR;没有正确的可聚焦窗口等情况也可能造成输入问题,不能只盯业务点击回调。

关键机制 ​

  • 设备侧:驱动 → EventHub → InputReader,得到 Android 输入事件。
  • 系统侧:InputDispatcher 根据窗口信息和策略确定目标,通过输入通道交接。
  • 应用侧:ViewRootImpl 接收,Activity / View 树分发,控件决定如何消费。

通俗例子 ​

屏幕上按钮可见,但上方有透明且可触摸的窗口覆盖:触摸可能被上层窗口接收,按钮的 onTouchEvent 根本没有机会执行。此时需要查窗口及输入目标,而不只是修改按钮点击监听。

追问与回答 ​

注册的输入回调里做耗时工作,会造成什么? ​

要先确认是哪一种回调、由哪个线程分发。普通触摸回调在主线程做耗时操作,会拖住输入处理和绘制;某些系统监控或原生输入回调还要求及时确认处理完成,拖延可能造成排队或超时。不能仅凭“注册了 IMS 回调”断言必然丢事件,应检查回调契约、线程、确认时机和队列证据。

onTouch 返回 true 和 onClick 有什么关系? ​

对通常处于 enabled 状态的 View,如果 OnTouchListener 消费了事件,后续 onTouchEvent 通常不会处理该事件,默认点击识别也就可能无法完成。onClick 不是每次触摸必定出现的独立通知,而是满足点击条件后的结果。自定义消费触摸并需要点击语义时,应在合适条件调用 performClick,兼顾可访问性。

易混淆点 ​

InputManagerService 与 InputMethodManagerService 不同,后者与软键盘等输入法管理有关;IMS 也不是 View 的事件拦截方法。输入事件传输不是每个触点都通过普通 Binder 方法调用 onTouchEvent。

参考资料 ​

内容来源 ​

用完整回答理解机制,用真实证据解释项目。