Android事件分发完全解析之为什么是她

记得以前教我code的启蒙老师对我说过,如果你想学习一个新事物只需要三个W:Why、What、How,也就是:为什么?是什么?怎么做?当你搞懂这三个W之后,你对新事物必定会有一个透彻的了解。然而对大多数Student来说他们往往最有兴趣的是“How”也是他们最先接触的一个W,其次则是“What”,而“Why”往往会被选择性地忽略,这也是很多时候我们为什么无法将现有知识水平提升一个层次的根本原因。

同样地,对于事件分发,我先不打算直接切入主题教大家如何如何看源码如何如何分析Android工程师们复杂的思维逻辑,如何如何去理清错综交杂的抽象层次。按照我们上面所说,我们先来试着追寻Android设计师们的思考方式尝试去理解为什么要有事件分发,大家都知道事件分发是Android事件处理的一个Breaking Point,难以理解,既然如此为什么要把这么复杂的东西作为Android的一部分呢?既然需要,那么其必定是必不可缺无法撼动的,but why?淡定,跟随大侦探爱尔摩斯来追寻这不为人知的丑陋秘密。

我们都知道,我们的手机或其他的手持设备甚至显示设备等等其显示区域都是有限的,即便是股票的大盘显示屏也是有限的,没有无限的视屏,更何况是巴掌大的一块显示区域。假设你是Android的一名设计师,要你来确定一种界面元素的显示方式,那么按照人传统的操作习惯和思维方式,你有且仅有两种选择:

Chioce A:

将界面元素以逐个排列的方式显示在屏幕上,如下图:

该方式可以让所有的界面元素都有属于自己独自的空间,对系统来说管理这些空间要简便得多,因为它们占有确定的屏幕区域,只需在显示时记录这些Area则可,各个元素互不干预。但是,瞎子也能看出来这样的显示方式有个明眼的弊端,随着界面元素的增加,一旦撑满屏幕,所有的元素大小都将被不断调整以便能放入更多的界面元素,而且,如果我们想将元素以叠加的方式排列,这样的显示方式是无法做到的,So,pass it。

Chioce B:

将界面元素层叠显示,每个元素理论上都拥有与显示设备尺寸一致的区域,如下图:

这么一来,我们可以在有限的显示设备区域内放下理论上无数个界面元素,同时还可以很好地解决掉Chioce A带来的很多限制问题。但是,世界并非完美的,即便在无所不能的code世界也总有缺陷。在Chioce A的方案中因为每个界面元素都有自己唯一的独立区域,每当用户以触摸显示设备的方式与之交互时总会Touch到唯一的一个元素。但是在Chioce B中则不行了……因为界面元素之间的层叠关系,每当我们触摸时都有可能Touch到N个层叠的元素,怎么办呢?这时我们就必须引入一套机制,让系统有能力去处理并判断用户想要Touch哪个元素,So,事件机制油然而生。

当然,事件机制的出现并非因为触摸屏,而上述的两种界面显示思想也并非来自Android的射鸡师,自显示设备出现的那天起便已存在,这里仅作一个引子抛砖引玉而已。

既然Choice B是我们的选择,那么我们应该如何对事件进行投递呢?Suppose我们有如下界面元素构成:

注:这里暂不考虑什么Window、DecorView等等,我们尽量抽象思维不要让思维惯性地和code靠在一起令逻辑变得复杂。

如上图所示,G为我们的显示设备屏幕,A、C、E都在G中为同一层级,而B、D、F分别在A、C、E中,其层叠效果就如上图所示,此时,假设我们
Touch屏幕中的某一区域,如下图中的红色区域:

这时按照人的行为模式F元素是应该获取到该Touch事件的,也就是说当Touch在屏幕G上发生后,交由F元素:

G----->F

交由F处理后那么F就有责任告知系统本次事件我吃掉了。但是这样会有个问题,如果说我们想让F下方的E也响应本次的Touch事件呢?那么我们的传递方式就该是这样的一个模式:

G----->F----->E

也就是说E和F都能吃掉该次事件,如果位于F和E下方的DCBA也要吃呢?这就陷入了一个窘境,每次谁要吃我们是事先不知道的,有可能谁一时兴起要吃掉该次事件,如果按照我们当前的这种“置顶优先”的方式来传递事件肯定是不科学的,同时也不符合我们界面元素层叠结构之间的关系。那么好办了,我们从底层开始传递事件,还是拿上图的Touch点来说,当触摸区域在上图的红色位置时,我们可以让系统通过一系列的计算获知事件点所在区域,一旦发现事件点落在某个界面元素的范围内(上图中事件点在所有的元素范围内)那么我们就按其层叠顺序依次将事件出递出去,比如上图中,事件由屏幕G点出发途径:

G----->A----->B----->C----->D----->E----->F

这样一次事件就可以依次经过多个可能捕获它的元素,这样的传递方式有一个专业的称谓:隧道式传递。一旦某个元素想要吃掉该次事件那么我们只需通过一定的逻辑处理告知系统本次事件我吃掉了,你不需要再传递给别人了!这时,我们就该把这个信号层层递交返回给系统,这种递交的方式也有一个有趣的名字:冒泡机制。就像水里的鱼在某个位置吐泡,总会冒回水面的。而这种以链式结构传递的方式在设计模式中也有迹可循,具体的饭迎大家关注SM哥的SAOS开源组织发起的Android与设计模式系列下Aige出品的责任链模式。当然你也可以让一次事件无序传递甚至乱传,只不过不提倡而已。

在Android的实际处理中事件机制绝非上面我们说的那么简单,上面的分析仅仅是一个浓缩版的事件机制结构。本节仅为一个开端,作为详解事件机制的一个引子没有代码的涉及,本来在编写自定义系列的交互文章时发现肯定会涉及事件机制,如果一起写显得太臃肿,干脆分开来更好地阐述,本系列作为一个中间桥梁上连自定义系列,下接GUI框架剖析,So,敬请关注。

时间: 2024-11-13 06:19:15

Android事件分发完全解析之为什么是她的相关文章

Android事件分发完全解析之事件从何而来

尊重原创转载请注明:From AigeStudio(http://blog.csdn.net/aigestudio)Power by Aige 侵权必究! 炮兵镇楼 上一节Android事件分发完全解析之为什么是她中我们简略地分析了事件分发机制的由来,这里要说明一点,Android(或者说任何的驱动系统)都包含大量不同类型的事件,比如按键啦.轨迹球啦.鼠标啦.触摸啦.红外线啦等等等,这里为了简化问题也为了切合实际,我们只针对触摸事件进行分析,至于其他的一些杂七杂八的事件其实都很好理解就不多说了.

Android事件分发机制完全解析,带你从源码的角度彻底理解(上)

转载请注明出处:http://blog.csdn.net/guolin_blog/article/details/9097463 其实我一直准备写一篇关于Android事件分发机制的文章,从我的第一篇博客开始,就零零散散在好多地方使用到了Android事件分发的知识.也有好多朋友问过我各种问题,比如:onTouch和onTouchEvent有什么区别,又该如何使用?为什么给ListView引入了一个滑动菜单的功能,ListView就不能滚动了?为什么图片轮播器里的图片使用Button而不用Ima

[转]Android事件分发机制完全解析,带你从源码的角度彻底理解(上)

Android事件分发机制 该篇文章出处:http://blog.csdn.net/guolin_blog/article/details/9097463 其实我一直准备写一篇关于Android事件分发机制的文章,从我的第一篇博客开始,就零零散散在好多地方使用到了Android事件分发的知识. 也有好多朋友问过我各种问题,比如:onTouch和onTouchEvent有什么区别,又该如何使用?为什么给ListView引入了一个滑动菜单的 功能,ListView就不能滚动了?为什么图片轮播器里的图

(转) Android事件分发机制完全解析,带你从源码的角度彻底理解(上)

转载请注明出处:http://blog.csdn.net/guolin_blog/article/details/9097463 其实我一直准备写一篇关于Android事件分发机制的文章,从我的第一篇博客开始,就零零散散在好多地方使用到了Android事件分发的知识.也有好多朋友问过我各种问题,比如:onTouch和onTouchEvent有什么区别,又该如何使用?为什么给ListView引入了一个滑动菜单的功能,ListView就不能滚动了?为什么图片轮播器里的图片使用Button而不用Ima

【转】Android事件分发机制完全解析,带你从源码的角度彻底理解(下)

转载请注明出处:http://blog.csdn.net/guolin_blog/article/details/9153761 记得在前面的文章中,我带大家一起从源码的角度分析了Android中View的事件分发机制,相信阅读过的朋友对View的事件分发已经有比较深刻的理解了. 还未阅读过的朋友,请先参考 Android事件分发机制完全解析,带你从源码的角度彻底理解(上) . 那么今天我们将继续上次未完成的话题,从源码的角度分析ViewGruop的事件分发. 首先我们来探讨一下,什么是View

Android View 的事件分发原理解析

作为一名 Android 开发者,每天接触最多的就是 View 了.Android View 虽然不是四大组件,但其并不比四大组件的地位低.而 View 的核心知识点事件分发机制则是不少刚入门同学的拦路虎,也是面试过程中基本上都会问的.理解 View 的事件能够让你写出更好自定义 View 以及解决滑动冲突. 1. View 事件认识 1.1 MotionEvent 事件 当你用手指轻触屏幕,这个过程在 Android 中主要可以分为以下三个过程: ACTION_DOWN:手指刚接触屏幕,按下去

Android事件分发机制详解:史上最全面、最易懂

前言 Android事件分发机制是每个Android开发者必须了解的基础知识 网上有大量关于Android事件分发机制的文章,但存在一些问题:内容不全.思路不清晰.无源码分析.简单问题复杂化等等 今天,我将全面总结Android的事件分发机制,我能保证这是市面上的最全面.最清晰.最易懂的 本文秉着"结论先行.详细分析在后"的原则,即先让大家感性认识,再通过理性分析从而理解问题: 所以,请各位读者先记住结论,再往下继续看分析: 文章较长,阅读需要较长时间,建议收藏等充足时间再进行阅读 目

Android 事件分发机制具体解释

很多其它内容请參照我的个人网站: http://stackvoid.com/ 网上非常多关于Android事件分发机制的解释,大多数描写叙述的都不够清晰,没有吧来龙去脉搞清晰,本文将带你从Touch事件产生到Touch事件被消费这一全过程作全面的剖析. 产生Touch事件 这部分牵扯到硬件和Linux内核部分:我们简单讲述一下这部分内容,假设有兴趣的话能够參考这篇文章. 传递Touch事件 触摸事件是由Linux内核的一个Input子系统来管理的(InputManager),Linux子系统会在

Android事件分发机制(二)

这篇文章继续讨论Android事件分发机制,首先我们来探讨一下,什么是ViewGroup?它和普通的View有什么区别? 顾名思义,ViewGroup就是一组View的集合,它包含很多的子View和子VewGroup,是Android中所有布局的父类或间接父类,像LinearLayout.RelativeLayout等都是继承自ViewGroup的.但ViewGroup实际上也是一个View,只不过比起View,它多了可以包含子View和定义布局参数的功能.ViewGroup继承结构示意图如下所