由浅入深学习android input系统 - input事件如何传递到View

Posted 许佳佳233

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了由浅入深学习android input系统 - input事件如何传递到View相关的知识,希望对你有一定的参考价值。

概述

”View的事件分发“对于大多数android开发者而言都是比较熟悉的。

对此还不了解的读者,推荐看下笔者的相关文章:
完全理解android事件分发机制

那么这个事件究竟是如何从“触摸屏幕”到“View处理事件”的呢?
本系列将针对此疑问展开。

ViewRootImpl对事件的传递

View的所有更新UI的操作最终都必须经过操作系统在系统进程的处理,才能够通过硬件展示到用户面前。
ViewRootImpl担任了window与view的中间人的角色,View可以通过ViewRootImpl将更新UI的操作告知操作系统,而操作系统也可以将触摸等硬件层面操作通过ViewRootImpl反馈给View。

此块内容笔者专门写文章讲解过,对细节有兴趣的读者可以看下这篇文章:
ViewRootImpl源码解析 (一) - View的更新
ViewRootImpl源码解析 (二) - 事件分发

ViewRootImpl为起点的传递过程

ViewRootImpl.WindowInputEventReceiver.onInputEvent()是事件第一次传递到ViewRootImpl,随后通过一系列的处理可以传递到对应的View。
任务栈调用如下:

  • ViewRootImpl.WindowInputEventReceiver.onInputEvent()
  • ViewRootImpl.enqueueInputEvent()
  • ViewRootImpl.doProcessInputEvents()
  • ViewRootImpl.deliverInputEvent()
  • ViewPostImeInputStage.deliver()
  • ViewPostImeInputStage.onProcess()
  • ViewPostImeInputStage.processPointerEvent()
  • View.dispatchPointerEvent()
  • View.dispatchTouchEvent()

ViewRootImpl的事件从哪里来?

app进程在接受到系统进程的事件后,最终会传递给ViewRootImpl。

任务栈调用如下:

  • NativeInputEventReceiver.handleEvent()
  • NativeInputEventReceiver.consumeEvents()
  • InputEventReceiver.dispachInputEvent()
    (等同于ViewRootImpl.WindowInputEventReceiver.dispachInputEvent())
  • ViewRootImpl.WindowInputEventReceiver.onInput()

逻辑如下:

  1. NativeInputEventReceiver监听系统进程发来的事件,收到后就会在handleEvent方法中处理。
  2. 在NativeInputEventReceiver的consumeEvents()方法中会通过JNI调用到InputEventReceiver的dispachInputEvent()方法。而此处的InputEventReceiver实际上是它的子类ViewRootImpl.WindowInputEventReceiver。
  3. 在ViewRootImpl.WindowInputEventReceiver的dispachInputEvent()方法中,最终会调用到onInput()方法。
  4. ViewRootImpl.WindowInputEventReceiver的dispachInputEvent().onInput()方法就是上面说的ViewRootImpl的事件分发的入口。后面就会在ViewRootImpl中传给View。

事件监听初始化

任务栈如下:

  • ViewRootImpl.setView()
  • WindowInputEventReceiver构造函数
  • WindowInputEventReceiver父类InputEventReceiver构造函数
  • InputEventReceiver.nativeInit()
  • android_view_InputEventReceiver.nativeInit()
  • NativeInputEventReceiver.initialize()
  • NativeInputEventReceiver.setFdEvents()
  • Looper.addFd()

逻辑如下:

  1. ViewRootImpl在setView()中初始化WindowInputEventReceiver,WindowInputEventReceiver的构造函数会调用到InputEventReceiver.nativeInit()方法。
  2. InputEventReceiver.nativeInit()是native方法,因此直接走到JNI的逻辑中,调用到android_view.InputEventReceiver.nativeInit()。
  3. nativeInit()中初始化了NativeInputEventReceiver,并且调用了NativeInputEventReceiver的initialize()方法。
  4. NativeInputEventReceiver的initialize()方法中调用了setFdEvents(),其中通过调用Looper.addFd()方法,对这条链路的事件进行随时监听。
  5. Looper中一旦收到事件,最终就会调用到NativeInputEventReceiver.handleEvent()方法。
    即上面分析”ViewRootImpl的事件从哪里来?“的入口。

以上是关于由浅入深学习android input系统 - input事件如何传递到View的主要内容,如果未能解决你的问题,请参考以下文章

由浅入深学习android input系统 - input系统的启动

由浅入深学习android input系统 - input事件采集(InputReader)

由浅入深学习android input系统 - input事件采集(InputReader)

由浅入深学习android input系统 - input事件如何传递到View

由浅入深学习android input系统 - input事件如何传递到View

由浅入深学习android input系统 - InputChannel解析