Android「打工人」:谁说事件分发很简单的,我被这个给虐哭了!

2020-11-18 17:59:17 浏览数 (1)

今天这周上班第一天给大家娱乐一下,给大家讲讲事件分发,你可能会一笑:“别搞我呀,事件分发谁不知道呀。”

但是,今天的内容,可能真的有你不知道的。

注意:如果你对事件分发原理并不是太了解,那么需要先对事件分发有足够的了解,最后再进行后续的阅读。

下面开始正文,因为这个问题是与同事间交流产生,所以本文以对话形式呈现。

主角:

小 A,小 B。

小 A:B 啊,你给我言简意赅的讲讲事件分发的流程。

小 B:好嘞。

“事件分发是针对一次手势的过程,这个手势包含一次 ACTION_DOWN,多次 ACTION_MOVE,和一次 ACTION_UP”,在 ACTION_DOWN 的时候来决定本次事件的“TargetView”,该 View 会决定这次事件分发的事件流向。

父控件可以在 ACTION_DOWN或者 targetView不为空的情况下,进行拦截,如果拦截了 targetView 的事件,会给它发一个 ACTION_CANCEL。

小 A:回答的可以呀,我来考你几个问题。

小 B:尽管来。

小 A:你说一次事件分发过程中会有多次ACTION_POINT_DOWN吗?

小 B内心:这不是送分题么,看样子小 A 兄弟对于多指这块不太熟悉呀,这都能做为问题。

小 B:当然可以,多指的时候,你按下第一个手指,再按下第二个手指ACTION_POINTER_DOWN就来了。

你可以看看 ViewPager,ScrollView 这些官方类源码,都有多指的处理。

小 A:鬼魅一笑,然后那我再问你,一次事件分发过程中,可能会有多次ACTION_DOWN吗?

小 B:等等,如果我答对了,一瓶可乐。

小 A:好。

小 B:没有,只有你第一个手指按下才是 ACTION_DOWN,从第二个开始都是ACTION_POINTER_DOWN,当然了前提是你自己不修改 dispatchTouchEvent 分发逻辑哈,改了可不算,是不是要去买可乐了。

小 A:好,最后我再问你一个具体的问题,一个 LinearLayout 内部有两个 Button,当我第一个手指按在第一个 Button 上,第二个手指按在第二个 Button 上,这两个 Button哪个会收到 ACTION_DOWN?分别抬起每个手指,哪个 Button 的 Click 会被触发?

小 B:当然是第一个收到 ACTION_DOWN,那么应该也是第一个能触发 click。

小 A:不错不错,你先去做个实验,再决定要不要我去买可乐。

对话结束。

到这里大家觉得小 B 回答的怎么样?

先别往下看,自己想想自己的回答应该是什么,如果错了,麻烦给我买瓶可乐。

小 B 回去测试。

大吼一声:为了可乐!

快速写完 Demo,分为自定义了一个 MyLinearLayout,MyButton,复写dispatchTouchEvent,打上 Event 日志,再加上 onclick 事件日志。

按照之前的描述实验:

一个 LinearLayout 内部有两个 Button,当我第一个手指按在第一个 Button 上,第二个手指按在第二个 Button 上,这两个 Button哪个会收到 ACTION_DOWN?分别抬起每个手指,哪个 Button 的 Click 会被触发?

看到 Log,心凉了。

第一个手指按下第一个 Button 上,第一个 Button 收到 ACTION_DOWN。 第二个手指按在第二个 Button 上,第二个 Button 竟然也收到了 ACTION_DOWN。

分别抬起时,两个 Button 的 Click 依次触发。

注意:大家测试的时候,Button 可以搞大一些,两个 Button 距离远一些,防止误触。

小 B带着两瓶可乐来到小 A 面前,大哥赶紧给我讲讲。

小 A:

好,在非常早期,很多博客的事件分发代码都是基于 2.x 系列的,那会代码是这样的:

完整代码见这里

MotionTarget 就是一个 View。而在后续的代码,"targetView"已经不再是一个独立的 View 了,而是一个类似于链表。

代码语言:javascript复制
// First touch target in the linked list of touch targets.
private TouchTarget mFirstTouchTarget;

private static final class TouchTarget {

    // The touched child view.
    public View child;

    // The next target in the target list.
    public TouchTarget next;
}

你顺着这个差异去看源码就明白了。

小 B:这波不亏,虽然亏了两瓶可乐,但是学到了。

好了,AB 角色结束,对话内容基本上是同事间日常对话,当然我故意润色了一些。

再次友情提示:在面试的时候,不要故意显摆你知道一个事件分发逻辑可能有多个 ACTION_DOWN,一定要分情况说清楚,因为面试官很可能没看过这篇文章,把你挂了别怪我...

最后

其实对于程序员来说,要学习的知识内容、技术有太多太多,要想不被环境淘汰就只有不断提升自己,从来都是我们去适应环境,而不是环境来适应我们!

这里附上上述的技术体系图相关的几十套腾讯、头条、阿里、美团等公司19年的面试题,把技术点整理成了视频和PDF(实际上比预期多花了不少精力),包含知识脉络 诸多细节,由于篇幅有限,这里以图片的形式给大家展示一部分。

相信它会给大家带来很多收获

以上内容均放在了开源项目:github 中已收录,里面包含不同方向的自学Android路线、面试题集合/面经、及系列技术文章等,资源持续更新中...

当程序员容易,当一个优秀的程序员是需要不断学习的,从初级程序员到高级程序员,从初级架构师到资深架构师,或者走向管理,从技术经理到技术总监,每个阶段都需要掌握不同的能力。早早确定自己的职业方向,才能在工作和能力提升中甩开同龄人。

最后如果你和小B错的一样,可乐我就不要了,点个赞可以吧~

0 人点赞