原来Android触控机制竟是这样的?

image

有什么料?

从这篇文章中你能获得这些料:

  • 了解一次触摸事件究竟是如何产生的?
  • 了解触摸事件究竟是如何传递的?
  • 学会从根源处分析你的App中的滑动冲突。
  • 能够更自信的创作出具有复杂交互的App。
  • 收获一张图,帮助你理解和使用Android的触摸事件分发。

link

老规矩,先来看图吧。

image

在你触摸屏幕之后

首先在上图中找到那只黑手,它是一次触摸事件的开始。

当屏幕被触摸,Linux内核会将硬件产生的触摸事件包装为Event存到/dev/input/event[x]目录下。对,你没看错,事件被搞成文件保存了下来!

接着,系统创建的一个InputReaderThread线程loop起来让EventHub调用getEvent()不断的从/dev/input/文件夹下读取输入事件。

然后InputReader则从EventHub中获得事件交给InputDispatch

InputDispatch又会把事件分发到需要的地方,比如ViewRootImplWindowInputEventReceiver中。

以上过程是在底层中完成,大部分由c++实现,我们了解流程就行。

image

下面从ViewRootImpl收到触摸事件开始分析触摸事件的去向。

触摸事件的旅行

第一站:从InputEventReceiver开始

我们现在图中找到WindowInputReceiver。可以看到,它继承了InputEventReceiver,并且是ViewRootImpl的一个内部类。

ViewRootImpl.java

final class WindowInputEventReceiver extends InputEventReceiver{

  @Override
  public void onInputEvent(InputEvent event) {
    ...
    enqueueInputEvent(event, this, 0, true);
    ...
  }
}

当一个输入事件产生时(这里我们认为是触摸事件),会回调InputEventReceiver.onInputEvent()。从名字也可以看出,它是接收输入事件的。然后进一步调用 ViewRootImpl.enqueueInputEvent() 将输入事件加入单链表队列。

ViewRootImpl.java

void enqueueInputEvent(InputEvent event,
    InputEventReceiver receiver, 
    int flags, 
    boolean processImmediately) {
    ...
    mPendingInputEventTail = q;
    //进行队列操作后,
    //将ViewRootImpl的mPendingInputEventTail复制为新的触摸事件。
    ...
    if (processImmediately) {
        doProcessInputEvents();
        //立即处理事件
    } else {
        scheduleProcessInputEvents();
        //走一遍Handler延迟处理事件
    }
}

上面这个方法主要对触摸事件进行队列操作(即排了个序),然后再根据processImmediately参数,决定是立即处理,还是延后处理。

下面看看是如何进行处理的。

void doProcessInputEvents() {
    while (mPendingIn
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值