Android事件分发机制小结
Android事件分发机制小结
触摸事件的产生到Activity的过程
-
当手指触摸屏幕时,linux会将触摸信号记录到dev/input目录下的文件中
-
IMS底层会开启两个线程:InputReaderThread和InputDispatcherThread
- InputReaderThread用于监听dev/input目录下的文件,并将触摸信号封装后交给InputDispatcherThread线程进行分发;监听文件变化是通过Inotify和epoll实现
-
ViewRootImpl在setView的时候,会创建InputChannel,通过WindowManager传递给IMS,IMS通过这个InputChannel向APP进程发送触摸事件;
- InputChannel底层是通过基于FD文件的SocketPair实现;一端的InputChannel只用于发送消息,另一端的InputChannel只用于接收消息
-
当ViewRootImpl这边接收到IMS那边发送过来的一个触摸事件后,最终会调用Activity的dispatchTouchEvent;
-
Activity又会通过对应的PhoneWindow转发给DecorView,DecorView调用ViewGroup的dispatchTouchEvent一层一层往下分发触摸事件
触摸事件从Activity开始往下层分发过程
-
ViewGroup会先调用onInterceptTouchEvent判断当前ViewGroup需不需要拦截当前触摸事件,如果需要则会调用ViewGroup的onTouchEvent,事件分发就结束了
-
如果ViewGroup不需要拦截,则遍历所有的子View,找到触摸事件触摸到的那个View,并保存到TouchTarget;之后的move、up、cancel事件都会直接转发给那个View,避免每个触摸事件都要循环遍历一遍去查找View
-
如果找到的那个View是个ViewGroup,则会继续往下面分发
-
如果找到的那个View是个普通View,则先判断有没有设置onTouch事件,如果有设置的话,会先调用Touch事件的onTouch方法,这个方法里如果返回true,表示消费了这个触摸事件,那么后续就不再调用该View的OnTouchEvent方法
-
如果Touch事件的onTouch方法里返回false,则会接着调用该View的OnTouchEvent方法,在这个方法里又会去判断是否有设置点击事件,如果有的话则会触发它的onClick方法
-
如果分发到最下层的View都没有View消费该触摸事件,则该触摸事件又会一层往回走,一次调用各个父View的onTouchEvent方法,最后调用到Activity的onTouchEvent方法后结束