Android事件分发详解-心得

来源:互联网 发布:nginx 不允许加参数 编辑:程序博客网 时间:2024/05/23 11:54

Android事件分发详解-心得

最近在搞自定义veiw的动画以及手指事件的效果交互,对以前看的事件分发机制又再次回顾了下,真的是忘干了…本着挤一点写一点的原则,在此记录一下失去的脑细胞。可以仔细看一下

  • 事件的传递模式
  • 重要的几个方法
  • 源码解析
  • 看图说话 —————————————注意这里!注意这里!注意这里!这个是心得,大家可以仔细看看
  • 流程图

事件的传递模式

事件的传递模式是典型的责任链模式,它包含了一些命令对象和一系列的处理对象。每一个处理对象决定它能处理哪些命令对象,它也知道如何将它不能处理的命令对象传递给该链中的下一个处理对象。具体请参考责任链模式.

这里写图片描述

以上是一个整体view的结构;

  • phowwindow可以理解为一个抽象类,是所有视图的最顶层容器,视图的外观和行为都归他管,不论是背景显示,标题栏还是事件处理都是他管理的范畴。

  • DecorView可以理解为我们展示的ContentView, 是 PhoneWindow 的一个内部类,就是跟在 PhoneWindow 身边专业为 PhoneWindow 服务的,除了自己要干活之外,也负责消息的传递,PhoneWindow 的指示通过 DecorView 传递给下面的 View,而下面 View 的信息也通过 DecorView 回传给 PhoneWindow。(另一部分就是我们所说的沉浸式标题栏的显示)
    这里写图片描述


重要的几个方法

dispatchTouchEvent:事件分发的方法,特别重要,事件的传递、反馈、都要经过它,相当于一个执行者方法;
onInterceptTouchEvent: 事件拦截的方法,注意,我们可以将其理解为一个工具方法,它的出现只在意结果,而不在于过程,相当于工具方法,
onTouchEvent 事件处理方法,事件的处理、反馈都要经过它,也相当于一个执行者方法

注意在Activity和跟根View中没有拦截方法,因为一个是事件的起点一个是事件的终点,拦截对于它们没有意义。就相当于一个公司的最高层,他所做的事情就是将任务分配下去,他如果亲自动手他也不需要降这个事件拦截下来,他做完就做完了,他是老大,不需要通知你,而你是码农,底层,你不做也得告诉你的上级,你没有拦截的可能,你没完成一大堆吃瓜群众都知道,所以你也不需要拦截的方法

或者这样理解:把onInterceptTouchEvent当成一个责任机制,判断我是否需要对这个事件负责,如果这件事很严重,而且这个事情我就是责任人,那就把这个事件拦截下来,还是自己做最安心,如果自己不是责任人,追不到自己头上,就先让下级去做;公司老大:谁敢追究老大的责任?(所以不需要这个方法) 你(码农):出了事情就要瑟瑟发抖(你也不需要这个方法)

类型 方法 Activity ViewGroup View 事件分发 dispatchTouchEvent √ √ √ 事件拦截 onInterceptTouchEvent × √ × 事件处理 onTouchEvent √ √ √

事件分发的流程如下:

Activity -> PhoneWindow -> DecorView -> ViewGroup -> … -> View

如果view没有处理,会将事件再次传递回去,如果Acctivity也么有处理,那么事件就会被丢掉

Activity <- PhoneWindow <- DecorView <- ViewGroup <- … <- View

有点类似于在工作上的一个场景:

老板:技术部,你过来看看他们这个动画怎么做的?挺好看的,你们去把他实现了。 - - - - - - 老板 dispatchTouchEvent

技术老大:老板看到一个动画,挺不错的,你看看怎么实现吧,我还有事。 - - - - - - 技术老大dispatchTouchEvent
(老大dispatchTouchEvent 时思考了一下 onInterceptTouchEvent 独白:我特么是老大,先让臭鱼烂虾试试)

组长:这个动画你能做出来吗?有没有好的思路? 你去试一下- - - - - - 组长dispatchTouchEvent

(组长dispatchTouchEvent 时思考了一下 onInterceptTouchEvent :我擦,这特么怎么实现的,好像没有特别好的思路,让你去做吧,我在考虑考虑)

:让我想一下吧- - - - - - 你dispatchTouchEvent

….(一秒钟)

:做不出来!- - - - - - 你onTouchEvent

组长:报告老大,他说做不了!- - - - - - 组长onTouchEvent

技术老大:报告老板,臭鱼烂厦们做不出来!- - - - - - 技术老大onTouchEvent

老板:是时候招一批新人了- - - - - - 老板onTouchEvent


源码解析

出于读者体验的考量,在这里,我将剔除掉一大堆无关痛痒的代码,讲一下核心的思路

public boolean dispatchTouchEvent(MotionEvent ev) {    boolean result = false;             // 默认状态为没有消费过    if (!onInterceptTouchEvent(ev)) {   // 如果没有拦截交给子View,所以说将dispatchTouchEvent当作一个工具方法        result = child.dispatchTouchEvent(ev);    }    if (!result) {                      // 如果事件没有被消费,询问自身onTouchEvent        result = onTouchEvent(ev);    }    return result;}

如果是走普通的流程,dispatchTouchEvent方法我们一般不会重写,返回的都是super.dispatchTouchEvent(),也就代表着所有的业务逻辑将由整套的view共同完成,如果直接返回true ,相当于直接将事件标为已经处理了,返回false的话,就是去调用自己的onTouchEvent

这里引用下Kelin的图片

这里写图片描述

没图言叼,这里仔细看一下

看图说话

1.顶层的是activity 是你们的老板(爹),他如果想做一件事情不走公司流程(dispatchTouchEvent()返回true或者false),那么这个事件你们全公司的人都不会知道,因为这个事件已经没有了(消费了)。返回false:这件事情很严重我的手下没有一个敢负责的,如果做了肯定是我负责,那算了这件事还是不想了(很可能是违法的事情- -)。返回true:这件事情根本没有意义,直接作废。

2.下属如果接收到一件任务,他在分发时先会看是否走公司流程,如果走公司流程(dispatchTouchEvent()返回super.dispatchTouchEvent()),如果他觉得这个事情无关痛痒,他又想有个交代,就直接返回true,表示这件事做完了,大家不用管了(反正是无关痛痒的事情,也不会有人调查,随他去吧)。如果这件事情有非常重要觉得自己都不敢对它负责,那就告诉大家(返回false)这件事不是我们能解决的,交给老大去做把。交给上级的onTouchEvent。

3.如果走公司流程,他会看看自己是不是要直接对该事情负责(出了问题可是要找出背锅侠的),如果不用负责,或者直接负责人不是他,只是连带负责人,就不拦截onInterceptTouchEvent()返回false或者super…;如果就是自己负责,就直接自己解决,就拦截下来onInterceptTouchEvent()返回true这样对自己最安全。

4.如果自己拦截下来,就去执行自己的onTouchEvent,如果很简单就做了(返回true),如果发现很难,做了有问题,就告诉自己的大佬:我做了但是做不出来(返回false super),然后就是大佬来执行onTouchEvent,如果大家都是臭鱼烂虾,都做不出来,那么大家都默不作声,让它随风而去吧,第二天正常上班(告诉自己我们努力过)

5.如果自己不拦截下来,这件事的负责人不是我,反正我还有手下,交给手下去做。

6.事件到了你这里,你是码农,你做不出来肯定就是你的责任了,所以你根本不用考虑是否拦截(所以你没有这个方法),但是你也可以知道这件事的性质,如果是个无关痛痒的事情,那就告诉大家,我做完了(dispatchTouchEvent返回true,反正大家都不会查),如果发现自己做不了,那就老老实实告诉自己的大佬(坦白从宽dispatchTouchEvent返回false交给大佬们去做),如果觉得可以试一试,走公司章程(dispatchTouchEvent返回super),就去执行自己的onTouchEvent,如果做完了就返回true,事件到此结束,如果意识到自己是臭鱼烂虾,就返回flase,告诉自己的大佬,我菜的抠脚没做出来…


流程图

红色箭头方向表示事件分发方向
绿色箭头方向表示事件回传方向。
谢谢大神的图

点击View事件被View消耗

这里写图片描述

点击 View区域但事件被 ViewGroup 拦截
这里写图片描述

这里写图片描述

                            看看这个图,能不能便于理解,就看你的悟性了。                    大家可以仔细看看**看图说话**部分,对于了解过程会很轻松!                                    抠脚来的,不喜勿喷哦。

原创粉丝点击