由浅入深学习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()
逻辑如下:
- NativeInputEventReceiver监听系统进程发来的事件,收到后就会在handleEvent方法中处理。
- 在NativeInputEventReceiver的consumeEvents()方法中会通过JNI调用到InputEventReceiver的dispachInputEvent()方法。而此处的InputEventReceiver实际上是它的子类ViewRootImpl.WindowInputEventReceiver。
- 在ViewRootImpl.WindowInputEventReceiver的dispachInputEvent()方法中,最终会调用到onInput()方法。
- ViewRootImpl.WindowInputEventReceiver的dispachInputEvent().onInput()方法就是上面说的ViewRootImpl的事件分发的入口。后面就会在ViewRootImpl中传给View。
事件监听初始化
任务栈如下:
- ViewRootImpl.setView()
- WindowInputEventReceiver构造函数
- WindowInputEventReceiver父类InputEventReceiver构造函数
- InputEventReceiver.nativeInit()
- android_view_InputEventReceiver.nativeInit()
- NativeInputEventReceiver.initialize()
- NativeInputEventReceiver.setFdEvents()
- Looper.addFd()
逻辑如下:
- ViewRootImpl在setView()中初始化WindowInputEventReceiver,WindowInputEventReceiver的构造函数会调用到InputEventReceiver.nativeInit()方法。
- InputEventReceiver.nativeInit()是native方法,因此直接走到JNI的逻辑中,调用到android_view.InputEventReceiver.nativeInit()。
- nativeInit()中初始化了NativeInputEventReceiver,并且调用了NativeInputEventReceiver的initialize()方法。
- NativeInputEventReceiver的initialize()方法中调用了setFdEvents(),其中通过调用Looper.addFd()方法,对这条链路的事件进行随时监听。
- Looper中一旦收到事件,最终就会调用到NativeInputEventReceiver.handleEvent()方法。
即上面分析”ViewRootImpl的事件从哪里来?“的入口。
以上是关于由浅入深学习android input系统 - input事件如何传递到View的主要内容,如果未能解决你的问题,请参考以下文章
由浅入深学习android input系统 - input系统的启动
由浅入深学习android input系统 - input事件采集(InputReader)
由浅入深学习android input系统 - input事件采集(InputReader)
由浅入深学习android input系统 - input事件如何传递到View