一、Native层
- 主要包含InputReader线程和InputDispatcher线程,都是通过Looper循环不停监听和处理点击事件。
- InputReader线程使用EventHub的getEvents获取点击事件。EventHub通过监听系统的
/dev/input节点实现。使用了epoll机制 - InputReader和InputDispatcher各自都有点击事件的队列,存储点击事件。
- 点击事件收到后,需要在Native层寻找目标窗口,然后直接通过JNI派发到应用进程。
二、ViewRootImpl层
android.view.ViewRootImpl.WindowInputEventReceiver#onInputEvent是Java层处理函数。- 一个点击事件会经过很多的
android.view.ViewRootImpl.InputStage进行处理,采用了责任链设计模式,其中TouchEvent使用ViewPreImeInputStage处理。
三、分发过程
- 首先分发到
Activity的dispatchTouchEvent,然后通过PhoneWindow透传到跟View,也就是DecorView。 DecorView本身是ViewGroup类型,通过dispatchTouchEvent进行分发。- 首先
onInterceptTouchEvent判断ViewGroup本身是否拦截事件 - 如果不拦截,然后遍历所有的子View进行分发。如果子View消费点击事件,那么就结束流程。
- 如果所有的子View均没有消费点击事件,那么ViewGroup自己的
dispatchTouchEvent函数尝试消费点击事件。 - 如果根
DecorView都没有消费点击事件,那么Activity通过onTouchEvent尝试消费点击事件。
四、View的时序说明
dispatchTouchEvent中首先调用android.view.View.OnTouchListener#onTouch。- 然后是View本身的
android.view.View#onTouchEvent方法 android.view.View#onTouchEvent首先尝试android.view.View#mTouchDelegate代理对象消费点击事件。android.view.View.OnClickListener回调是最后收到的。并且是action_up之后才会收到click回调。
五、时序图
右键,在浏览器新的标签页中打开看完整时序图

参考
InputDispatcher线程:https://gityuan.com/2016/12/17/input-dispatcher/
InputReader线程:https://gityuan.com/2016/12/11/input-reader/