Android事件分发机制

当用户点击触摸屏时,该消息首先会被消息处理前端转换为更为明确的消息,比如DOWN/UP消息。然后通过WindowManagerSerview(后面用WMS缩写代替)根据消息的位置坐标去判断坐标的区域,下发给相应的窗口。

那么问题来了首先WMS怎么将消息分发到应用层的呢?

分析之前,我们需要对ViewRootImpl有个简单的了解。看名字有点像是一个View,然而并不是,它是用来和WMS通信。它向WMS注册了一个消息对象,来处理底层的时间消息。注册的过程是在ViewRootImpl.setView()方法中完成。当有触摸事件发生时,会通过ViewRootImpl的mView的方法接收点击事件,这个mView变量就是我们熟悉的DecorView。

接下来进入正题

首先我们看下DecorView.dispatchTouchEvent方法:

这个方法调用window.Callback.dispatchTouchEvent(),这里window.callback的实例其实就是Activity。那么我们继续看Activity的dispatchTouchEvent()方法

Android事件分发机制_第1张图片

在Activity的这个方法中,首先看当点击事件是开始,也就是ACTION_DOWN时,首先会调用onUserInteraction(),这个方法是一个空实现,相当于提供一个在点击事件开始时的操作入口。Activity的getVindow()获得的是Window的子类PhoneWindow。PhoneWindow.superDispatchTouchEvent()返回true。那么Activity的onTouchEvent将无法接受到触摸事件并进行处理。接下来我们看一下PhoneWindow中superDispatchTouchEvent()的实现。

此方法的内部是调用Decor.superDispatchTouchEvent()。DecorView是一个ViewGroup,其中的superDispatchTouchEvent()最后也是调用的ViewGroup的DispatchTouchEvent。至此,触摸事件传递成功过渡到了View和ViewGroup的体系当中。

ViewGroup继承了View,先从View入手

首先我们要知道在事件传递机制中,View所涉及的几个方法:dispatchTouchEvent,onTouchEvent,TouchListener.onTouch,ClickListener.OnClick。

首先从dispatchTouchEvent着手

Android事件分发机制_第2张图片

其中我们最关心应该是上图中的部分代码,dispatchTouchEvent包括了View的整个事件传递的控制。从上图的逻辑来看,当mTouchListener.onTouch()返回为true时(也就是我们常说的事件被消费了),整个方法执行结束。并不会执行到onTouchEvent(),此View自身的事件传递到此结束。但是dispatchTouchEvent()中我们没有看到click()的身影,那么click()是在什么地方才会去执行的呢,下面会进行慢慢分析。

当mTouchListener.onTouch()返回为false时(事件没被消费),我们需要关注onTouchEvent()。

Android事件分发机制_第3张图片

在View的onTouch方法中我们发现了performClick(),看名字我们应该也知道,此处是执行了click动作。

Android事件分发机制_第4张图片

我们从performClick()方法的源码中找到了我们需要知道的click()方法。至此,在事件分发机制中View所涉及到的方法都已出现。

总结一下View中的事件传递过程

dispatchTouchEvent()是整个View中事件传递的控制过程。其中最先执行的是onTouchListener.onTouch()。当事件被消费时,onTouchEvent和onClick将不会再执行。如果没有消费,则将执行到onTouchEvent()。

上面介绍了View自身的事件传递流程,但是在实际开发中,多层级的不急是不可避免的。那么我们还需要对ViewGroup的事件传递流程做一个简单了解。

同样从dispatchTouchEvent开始。

Android事件分发机制_第5张图片

既然是ViewGroup,必然会涉及到将事件分发至子View或子ViewGroup的过程。但是在分发事件之前有一个控制逻辑,可以中断事件传递到子View或ViewGroup。上图就是中断的部分,我们需要关注其中onInterceptTouchEvent()。我们可以自定义的ViewGroup中重载onInterceptTouchEvent(),当我们不希望某一个事件传递给子View或ViewGroup时,我们可以在onInterceptTouchEvent()进行一些操作然后return true。

当事件传递没有被中断时,首先会遍历所有的子View或ViewGroup,确认哪个子View或ViewGroup能够处理当前的事件。事件传递到下层是通过dispatchTransformedTouchEvent()。

Android事件分发机制_第6张图片

dispatchTransfromedTouchEvent()核心代码如上图所示。当ViewGroup的child为null时,则事件传递将调用父类View的dispatchTouchEvent()方法。当有子View或ViewGroupGroup时,调用child的dispatchTouchEvent()。

至此,我们对Android的事件分发机制有了总体的了解。当然上面的介绍和源码介绍略过了相当多的细节和逻辑,需要更细致的了解还是建议直接深入源码去解读。

(看,排版这么差的文章,一定是原创的!!!)

你可能感兴趣的:(Android事件分发机制)