事件分发之旅:从源码窥探事件流
2023-09-14 10:41:05
事件分发机制(二):源码篇
序言
继上篇博文对事件分发的精妙解析之后,我们踏上了探寻事件分发机制源码之旅。通过亲身深入源码,我们将从微观视角揭开事件流的奥秘。
事件流的U型之旅
事件分发,正如我们之前所述,宛如一个U型流。事件从Activity顶端出发,向下逐级传递,直至触及底部View。如果途中任何View消费了事件,U型流便在此中断,事件止步于此。反之,事件将继续下行,最终由Activity的onTouchEvent()方法处理。
源码剖析
1. onTouchEvent()方法
Activity的onTouchEvent()方法是事件流的终点。若事件未被任何View消费,该方法便负责处理剩余事件。其代码如下:
public boolean onTouchEvent(MotionEvent event) {
if (mDelegate != null) {
mDelegate.onTouchEvent(event);
} else {
return super.onTouchEvent(event);
}
}
如上所示,onTouchEvent()方法首先检查是否存在委托对象mDelegate。如果存在,则将事件委托给该对象处理;否则,调用父类方法处理。
2. dispatchTouchEvent()方法
dispatchTouchEvent()方法是事件流的核心。其负责将事件逐级向下传递给子View。其代码如下:
public boolean dispatchTouchEvent(MotionEvent event) {
if (!mAdded) {
return false;
}
boolean canConsume = onFilterTouchEventForSecurity(event);
if (!canConsume) {
return false;
}
// ...省略部分代码...
if (mFrameStats != null) {
mFrameStats.onTouchEvent();
}
int action = event.getAction();
if (mDelegate != null) {
mDelegate.onDispatchTouchEvent(event);
}
// ...省略部分代码...
}
dispatchTouchEvent()方法首先检查Activity是否已添加到Window中。如果不是,则直接返回false。接下来,它调用onFilterTouchEventForSecurity()方法,检查事件是否被安全过滤掉。如果是,则返回false。
之后,该方法执行以下操作:
- 更新帧统计信息。
- 获取事件动作类型。
- 将事件委托给mDelegate对象处理。
- 调用onInterceptTouchEvent()方法,检查事件是否被拦截。
- 如果事件未被拦截,则调用onTouchEvent()方法,将事件传递给当前View。
3. onInterceptTouchEvent()方法
onInterceptTouchEvent()方法由ViewGroup类实现,它决定是否拦截子View的触摸事件。其代码如下:
public boolean onInterceptTouchEvent(MotionEvent ev) {
if (mInputEventConsistencyVerifier != null) {
mInputEventConsistencyVerifier.onTouchEvent(ev, this);
}
int action = ev.getAction();
boolean intercepted = false;
// ...省略部分代码...
return intercepted;
}
onInterceptTouchEvent()方法首先调用InputEventConsistencyVerifier,用于检查触摸事件的合法性。然后,它获取事件动作类型并设置一个intercepted标志,表示事件是否被拦截。
接下来,该方法执行以下操作:
- 调用子View的onInterceptTouchEvent()方法,询问子View是否拦截事件。
- 根据子View的返回结果,更新intercepted标志。
- 返回intercepted标志,表示事件是否被拦截。
结论
通过对源码的深入剖析,我们更加清晰地理解了事件分发机制的运作原理。事件流如同一个U型流,从Activity逐级向下传递,直至最终被消费或处理。源码中的关键方法,如dispatchTouchEvent()和onInterceptTouchEvent(),扮演着至关重要的角色,控制着事件的流动。
本次源码之旅,不仅让我们深入技术细节,更让我们领略了Android底层框架的精妙设计。在未来的技术探索中,源码分析将始终作为我们获取真知灼见的宝贵途径。