View的事件响应主要有两种,
一个是Key按键,又细分 输入法前(keyPreIme),输入法后(经常用的key事件)
一个是Touch触摸,
点触摸通俗来说触摸事件是这个 而click事件是从Touch中分出的
轨迹球触摸
通用触摸事件
首先事件 从 输入子系统与IME息息相关
native层 中有Looper 和 NativeMessageQueue 以及MessageEnvelop
在nativepollonce,会调用native的MessageQueue pollOnce--》native的Looper pollOnce
--》把native的looper pollInner --》native的lopper的 epoll_wait阻塞线程。
epoll_wait释放线程有几种形式
timeout时间到
epoll_wait出错
java层调用nativeWake()
native层调用wake()
其他监听epollFd(轮询的FileDescriptior) 触摸事件和按键事件就是例子
epoll_wait的后续调用
input输入,调起,InputRead InputDispatcher
主要有native层Looper消息处理handleMessage
以及对监听的epollFd进行LooperCallback的handleEvent的处理
触摸事件以及按键时间
通过native NativeInputEventReceiver的handleEvent的回调
进而调用consumeEvents
由于java层的InputEventReceiver#dispatchInputEvent被封装在native层NativeInputEventReceiver的struts gInputEventReceiverClassInfo结构体中
最终通过回调,进入java层,开始事件分发操作
InputEventReceiver#dispatchInputEvent===>对标C中的native把InputEvent对象传到java中
调用ViewRootImpl中WindowInputEventReceiver(父类InputEventReceiver)#onInputEvent
通过责任链的形式进行传递
所有的类的父类是InputStage
是类方法deliver(q)开始调用,开始执行子类
子类主要重写方法是OnProcess()
通过apply()调用finish()调用forward()调用
责任链中下个子类
最外层NativePreImeInputStage在输入法之前,不支持point touch事件
内层1 ViewPreImeInputStage在输入法之前执行,不支持触摸事件,可以响应keyPreIme事件
内层2 ImeInputStage分发输入法开启输入法服务,不支持触摸事件
内层3 EarlyPostImeStage输入法之后,支持触摸事件和key事件,但View不去重写
内层4NativePostImeStage输入法之后
内层5ViewPostImeStage输入法之后分发,view各个层级,
最内层 SyntheticInputStage
有 Key事件
1分发到抽象类View的子类DecorView的dispatchKeyEvent()
2进一步分发到activity的实现Window.Callback的dispatchkeyEvent();
3进一步分发到PhoneWindow实现Window接口的superDispatchkeyEvent();
4进一步分发到ViewGroup的dispatchKeyEvent()
viewGroup本身进行处理调用View的dispatchKeyEvent()
当强ViewGroup子view得到focus,直接子view进行处理
5进一步分发OnkeyListener或者KeyEvent的dispatch();
进一步分发到View实现KeyEvent.Callback的onkeydown和onkeyup事件
6最终由activity的onkeydown和onkeyup事件兜底
在一步一步的从view层级中回去,知道事件响应结束
有Touch事件
点触摸通俗来说触摸事件是这个
1分发到抽象类View的子类DecorView的dispatchTouchEvent()
2进一步分发到activity的实现Window.Callback的dispatchTouchEvent();
3进一步分发到PhoneWindow实现Window接口的superDispatchTouchEvent()
4进一步分发到ViewGroup的dispatchTouchEvent()
viewGroup本身进行处理调用onInterceptTouchEvent(),子类view将不会响应触摸事件
上面没有拦截,分发到子view的dispatchTouchEvent();
5进一步分发到onTouchEvent()===》click事件在此处被执行
在一步一步的从view层级中回去,知道事件响应结束
1 MovetionEvent.DOWN
1.2 从父ViewGroup的dispatchTouchEvent开始
1.3 调到父ViewGroup的onInterceptTouchEvent
if 拦截不去响应子View,直接调用父ViewGroup的onTouchEvent
if 未消费返回false,整个touch事件结束
else 父ViewGroup消费了DOWN,调用 2
1.4 else没有拦截调用子View的dispatchTouchEvent
1.5 若设置了OnTouchListener调用onTouch
if 返回true,消费了DOWN 调用 2
1.6 else否则继续调用子View的onTouchEvent
if 未消费返回false,继续调用父ViewGroup的onTouchEvent
if 未消费返回false,整个touch事件结束
else 父ViewGroup消费了DOWN,调用 2
1.7 else子View消费了,DOWN 调用 2
2 然后继续MOVE,UP类似的流程
父ViewGroup的onTouchEvent 返回true
子View的OnTouchEvent 返回 false 或super.onTouchEvent
执行流程