背景
项目遇到点击事件和动画开始时机时序问题,在这整理点击事件产生过程,作备忘。
- 以下假设已经理解单次 Activity.dispatchTouchEvent 流程,包括 ViewGroup 和 View 处理
- 已知 android.view.View.OnClickListener#onClick 的执行时机和 android.view.View#onTouchEvent 不是同一 Message
- Java 层输入事件的入口在哪里?
问题
- 从主线程消息队列的角度看,从 MessageQueue.next 开始到收到 MotionEvent.Down 和 MotiveEvent.Up 事件的主要流程是怎么样的?
时序图
OnClick 来源- 由于 Android UI 设计成事件驱动,主线程会一直在 android.os.Looper#loop 中取 MessageQueue 中的 Message 出来执行
- MessageQueue 每次取一条消息时,先进入 native 层执行 native 消息队列中的消息,再取 Java 层的消息出来执行
- 执行 android.os.MessageQueue#nativePollOnce 时进入 native 层,对应 android_os_MessageQueue_nativePollOnce 函数,这时的目的是轮询 native 层消息队列是否有需要执行的消息
- 接下来 Looper#pollOnce 中遍历所有注册到其中的 LooperCallback,回调他们的 handleEvent 方法
- NativeInputEventReceiver 从 InputConsumer 中遍历当前需要处理的输入事件
- 拿到 MotionEvent 后通过 JNIEnv 对象调用 CallVoidMethod 进入 ART 虚拟机
- JNIEnv 对象把方法信息交给反射模块,查找到 InputEventReceiver 类和 ArtMethod 对象,把信息交给 ArtMethod 对象
- ArtMethod 配置调用参数,并进入汇编执行阶段,执行 android.view.InputEventReceiver#dispatchInputEvent 对应的机器码
- 这时进入了 java 层 android.view.InputEventReceiver#dispatchInputEvent 最后分发给 Activity 对象
- 如果从 DOWN 到 UP 时间很短,那么 NativeInputEventReceiver 会回调两次 CallVoidMethod 把事件传递给 Activity 对象
总结
- 了解了主线程在 native 层如何回调 Activity.dispatchTouchEvent 的
- 下一个问题,InputConsumer 如何取到输入事件的?用户点击屏幕,驱动层先知道这个信息,然后分发给应用层。但是源码在哪里?
网友评论