Da062f8aaec8a95cb8f45c40ab4d560a
学习 View 事件分发,就像外地人上了黑车

前言

今天和大家分享的是 View 事件分发。

原本这是作为深度思考练习的随笔,没打算发表公开。可没想到的是,我无法忘却 3 年前备受折磨的那个夜晚 —— 在我第一次学习 View 事件分发,却被网文折磨的那个夜晚 …

是网上介绍 View 事件分发的文章不够多吗?

不是的,恰恰相反,网上的爆文不计其数,待你仔细阅读,却 颇有一种“外地人上了黑车”的感觉 —— 一言不合先上 30 张图表,带你在城市外围饶个上百圈,就是不直奔主题 解释一个现象为什么会存在、造成它存在的缘由为何、它如此设计是为了解决什么问题 …

比起 拨开迷雾、明确状况、建立感性认识,他们更热衷于自我包装。

—— 有没有帮助我不管,先唬住人再说。

为了唬人,就算给他人徒添困扰、白费大量时间,也在所不惜 …

正是对那次痛苦经历的念念不忘,于是我 破例 将这篇文章分享给大家。

在此,我向 3 年前的那个自己发誓,我必在 结尾 200 字 就讲明白,别人非要绕个 3000、5000 字都讲不明白的事件分发。

不仅如此,我还要额外地帮助大家理解,事件分发流程中的 3 个小细节:之所以如此设计,是出于什么考虑。通过“知其所以然”,来方便大家更好地加深印象。

文章目录一览

  • 前言
  • View 事件分发的本质是递归
  • View 事件分发为何要设计成递归?
  • View 排版规则为何设计为“嵌套越深,显示层级越高”?
  • 所以,整个流程大致是怎样的?
  • 额外需要明确的 3 个小细节
    • 细节1:明确消费的概念
    • 细节2:明确拦截的作用
    • 细节3:拦截方法只走一次,不代表拦截只走一次
    • 细节4:ACTION_DOWN 不执行,那么没下次了
    • 细节5:内部拦截并不能阻止父容器对 ACTION_DOWN 的处理
  • 综上

View 事件分发的本质是递归

什么是递归呢?递归的本质是什么呢?

顾名思义,递归是一种包含 “递” 流程和 “归” 流程的算法。当我们在找寻目标时,便是处于 “递” 流程,当我们找到目标,打算从目标开始来执行事务时,我们便开启了 “归” 流程。

如果这么说有点抽象的话,不妨结合现实中的实例来理解下递归:

案例:职场任务的下发和上报,就是典型的递归

领导 自上而下、逐级地下达任务、寻找目标执行者,这就是 “递” 流程。

直到找到合适的执行者时,便开启了 自下而上 的 “归”流程。若当前执行者无法让结果 OK,那么上报给他的上级,由他的上级来执行,如果上级也不 OK,那么继续向上,直到结果 OK 为止。

伪代码来表示,即:

boolean dispatch() {
    if (hasTargetChild && child.dispatch()) {
        return true;
    } else {
        return executeByMySelf();
    }
}

View 事件分发为何要设计成递归?

如此设计,是为了与 View 的排版相呼应。

View 的排版规则是:嵌套越深的,显示层级越高。而显示层级越高,就越容易覆盖层级低的、被用户看见。

再加上,“所见即所得”,要求 “用户看到了什么,触控到的也该是什么”(简言之,操作要符合用户直觉)。

因此,正是考虑到嵌套越深,层级越高,触摸也通常会是交给层级高的来处理,因而也将事件分发设计成递归。

View 排版规则为何设计为“嵌套越深,显示层级越高”?

因为这符合常理。越外层的,作为父容器而充当背景,越里层的,作为子控件而至于前景。

<LinearLayout>
    <ScrollView>
        <TextView/>
    </ScrollView>
</LinearLayout>

所以,整个流程大致是怎样的?

首先我们要明确的 3 点是:

1.每次完整的事件分发流程,都包含自上而下的 “递”,和自下而上的“归” 2 个流程。

2.每次完整的事件分发流程,都是针对一个事件(MotionEvent)完成的递归,而一个事件只对应着一个 ACTION,例如 ACTION_DOWN。

3.一次用户触摸操作,我们称之为一个事件序列。一个事件序列会包含 ACTION_DOWN、ACTION_MOVE ... ACTION_MOVE、ACTION_UP 等多个事件。(其中 ACTION_MOVE 的数量是从 0 到多个不等)

也即一个事件序列,包含从 ACTION_DOWN 到 ACTION_UP 的多次事件分发流程。

下面我用一张图概括 View 事件分发的递和归流程。

top Created with Sketch.