Android点击事件被丢弃的类型与原因

Android点击事件被丢弃的类型与原因

InputDispatcher处理点击事件是单线程串行处理的,如果队列前面的点击事件一直无法处理,会导致后续点击事件迟迟无法响应,给用户的感知就是手机卡顿,所以在一些场景下,InputDispatcher必须丢弃一些未处理完成的点击事件。
DropReason枚举完整地描述了点击事件被丢弃的所有原因

  • DROP_REASON_POLICY:某些输入事件具有系统级的功能,例如HOME键、电源键、电话接听/挂断键等被系统处理,因此DispatcherPolicy不希望这些事件被窗口所捕获。当InputDispatcher在将输入事件放入派发队列前向DispatcherPolicy询问此事件的派发策略时,DispatcherPolicy会将POLICY_FLAG_PASS_TO_USER策略去掉。没有这个派发策略的对象会被丢弃。
  • DROP_REASON_APP_SWITCH:dispatchOnceInnerLocked()函数说明了InputDispatcher的事件派发是串行的。因此在前一个事件的派发成功并得到目标窗口的反馈前,后续的输入事件都会被其阻塞。当某个窗口因程序缺陷而无法响应输入时,懊恼的用户可能会尝试使用HOME键退出这个程序。然而遗憾的是,由于派发的串行性,用户所按的HOME键在其之前的输入事件成功派发给无响应的窗口之前无法获得派发的机会,因此在ANR对话框弹出之前的5秒里,用户不得不面对无响应的应用程序欲哭无泪。为了解决这个问题,InputDispatcher为HOME键设置了限时派发的要求。当InputDispatcher的enqueueInboundEventLocked()函数发现HOME键被加入派发队列后,便要求HOME键之前的所有输入事件在0.5秒(由APP_SWITCH_TIMEOUT常量定义)之前派发完毕,否则这些事件将都会被丢弃,使得HOME键至少能够在0.5秒内得到响应。
  • DROP_REASON_BLOCKED:和APP_SWITCH原因类似,如果是因为一个窗口无法响应输入事件,用户可能希望在其他窗口上进行点击,以尝试是否能得到响应。因为派发的串行性,这次尝试会以失败而告终。为此,当enqueueInboundEventLocked()发现有窗口正阻塞着派发的进行,并且新入队的触摸事件的目标是另外一个窗口,则将这个新事件保存到mNextUnblockedEvent中。随后的dispatchOnceInnerLocked()会将此事件之前的输入事件全部丢弃,使得用户在其他窗口上进行点击的尝试可以立刻得到响应。
  • DROP_REASON_DISABLED:因为InputDispatcher被禁用而使得事件被丢弃。InputDispatcher::setInputDispatchMode()函数可以使得InputDispatcher在禁用、冻结与正常三种状态之间进行切换。禁用状态会使得所有事件被丢弃,冻结将会使得dispatchOnceInnerLocked()函数直接返回从而停止派发工作。InputDispatcher的这三种状态的切换由Java层的IMS提供接口,由AMS和WMS根据需要进行设置。例如,当手机进入休眠状态时,InputDispatcher会被禁用,而屏幕旋转过程中,InputDispatcher会被暂时冻结。
  • DROP_REASON_STALE:在dispatchOnceInnerLocked()函数准备对事件进行派发时,会先检查一下事件所携带的时间戳与当前时间的差距。如果事件过于陈旧(10秒以上,由常量STALE_EVENT_TIMEOUT所指定),则此事件需要被抛弃。

参考

深入理解android卷三

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值