移动开发:你以为事件分发很简单,但我却被问哭了...
今天上班第一天给大家娱乐一下,给大家讲讲事件分发,你可能会一笑:“别搞我呀,事件分发谁不知道呀。”
但是,今天的内容,可能真的有你不知道的。
注意:如果你对事件分发原理并不是太了解,那么需要先对事件分发有足够的了解,最后再进行后续的阅读。
下面开始正文,因为这个问题是与同事间交流产生,所以本文以对话形式呈现。
主角:
小 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 了,而是一个类似于链表。
// 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(实际上比预期多花了不少精力),包含知识脉络 + 诸多细节,由于篇幅有限,这里以图片的形式给大家展示一部分。
相信它会给大家带来很多收获:
上述【高清技术脑图】以及【配套的架构技术PDF】可以 加我wx:X1524478394 免费获取!
当程序员容易,当一个优秀的程序员是需要不断学习的,从初级程序员到高级程序员,从初级架构师到资深架构师,或者走向管理,从技术经理到技术总监,每个阶段都需要掌握不同的能力。早早确定自己的职业方向,才能在工作和能力提升中甩开同龄人。
最后如果你和小B错的一样,可乐我就不要了,点个赞可以吧~