Android事件的分发机制简单理解

说起android 事件的分发机制,我主要是简单的讲述一遍事件分发机制的流程,可以快速的了解android事件分发的过程,不死扣源码的实现过程。

我们先大概的说一下大概的流程:一般当点击事件发生时(就是我们设置的事件发生时),先将该事件传到我们的Activity,在传到Viewgroup,最终传递到view。

以上是事件分发的最基本的流程,接下来我们挨个分析,首先我们从每个部分向下传递时,每个部分的作用:

从表格上也可以看出一个事件产生之后,都是先传给Activity,在传给ViewGroup,最后传给View,在这要注意的是我们的viewgroup虽然是在view的上层的(我理解的上层),但是viewgroup是继承自view的。接下来是传递的三个方法:

从表格中可以看到分别是dispatchTouchEvent() ,onTouchEvent(),onInterceptTouchEvent()这三个方法,具体的作用表格已经给出解释了。我们再来挨个分析这三个方法,首先我们要知道事件是从activity到viewgroup再到view的。所以activity中

是没有那个拦截拦截事件的,最高层的无法进行拦截。所以activity只有那个dispatchTouchEvent(),onTouchEvent()。再来看下一层的viewgroup中,刚才也提到了viewgroup是继承自view的所以view拥有的方法viewgroup也有。所以我们直接看view,view中是都包含这三个方法的dispatchTouchEvent() ,onTouchEvent(),onInterceptTouchEvent()。因为viewgroup是继承自view的所以viewgroup是包含super.dispatchTouchEvent() ,super.onTouchEvent(),super.onInterceptTouchEvent()

接下来具体分析他们的流程:

当一个点击事件发生时,事件最先传到Activity的dispatchTouchEvent()进行事件分发

分发方法dispatchTouchEvent该方法主要是负责分发,是安卓事件分发过程中的核心

如果某个组件的该方法返回TRUE,则表示该组件已经对事件进行了处理,不用继续调用其余组件的分发方法,

即停止分发。如果某个组件的该方法返回FALSE,则表示该组件不能对该事件进行处理,需要按照规则继续分发事件。

在不复写该方法的情况下,除了一些特殊的组件,其余组件都是默认返回False的。

从核心逻辑中看出,当事件传递给Activity后,它先将事件分发给子View处理。

如果经过子View层层传递或处理后,该事件被消费了(即返回了TRUE),则Activity的分发方法也返回TRUE,同样也表示该事件已经被消费了。

如果经过子View层层传递或处理后,该事件没有被消费(即返回了FALSE),则Activity的分发方法就不会返回TRUE了,而是调用onTouchEvent()去处理,看其实际的处理情况。

如果onTouchEvent消费了事件,那依然能返回TRUE(表示已消费事件),这个TRUE作为dispatchTouchEvent的返回值,让调用它的对象知道该Activity已经消费了事件

如果onTouchEvent没有消费该事件,那就返回FALSE(表示未消费事件),这个FALSE作为dispatchTouchEvent的返回值,让调用它的对象知道该Activity没有消费事件,需要继续处理。(注意:判断事件是否被消费是根据返回值,而不只你是否使用了该事件)

ViewGroup的dispatchTouchEvent方法

ViewGroup的该方法与Activity的类似,只是新添了一个onInterceptTouchEvent方法。当事件传入时,首先会调用onInterceptTouchEvent。

如果该方法返回了FALSE(表示不拦截),则交给子View去调用dispatchTouchEvent()方法

如果该方法返回了TRUE(表示拦截),则直接交给该ViewGroup对象的onTouchEvent(ev)方法处理,具体是否能处理以onTouchEvent()的实际情况为准。

实际上,在onInterceptTouchEvent返回TURE表示拦截时,实际调用的是super.dispatchTouchEvent方法,即View的该方法,进而由该方法调用onTouchEvent.因为viewGroup是继承子View的,所以是Super方法

View的dispatchTouchEvent方法

从该方法的核心逻辑中可以看到,事件传递进来后,首先会对mOnTouchListener判空,如果之前Set了Listener,则会调用其onTouch方法。

若onTouch方法返回TRUE,则dispatchTouchEvent也会返回TRUE,表示消费该事件。

若onTouch方法返回FALSE,或者mOnTouchListener本来就是空,则调用自身的onTouchEvent()来处理,是否消费事件,

可以由其返回值判断。实际上,在View的onTouchEvent方法中,如果设置了onClickListener监听对象,则会调用其onClick

方法。在同时设置了onTouchListener与onClickListener对象的情况下,正是由于View的dispacthTouchEvent方法会先调用mOnTouchListener的onTouch,才会调用onTouchEvent方法,所以onTouchListener对象的onTouch方法是优先于onClickListener对象的onClick方法调用的。

 

 

大体流程:事件传到Activity,首先调用其dispatchTouchEvent方法,其会传递给子View处理,该子View(在图中是ViewGroup)会调用其dispatchTouchEvent方法,如果该方法被覆写直接返回TRUE,则立即返回Activity,表示已经消费事件。如果该方法没有被覆写或调用了super的同名方法,则会调用onInterceptTouchEvent方法,如果该方法返回TRUE拦截事件,则交给自身的onTouchEvent处理,如果该方法返回FALSE不拦截,则继续传给子子View(图中是View)的dispatchTouchEvent方法处理。这就是android事件分发机制的大体流程。

注意:OnTouchListner的优先级高于onTouchEvent,如果OnTouchListner返回true,onTouchEvent就不执行,反之,则会调用

如果事件一直没有被消费,最后会传给Activity,如果Activity也不需要就被抛弃。

接下来我们再分析一下几个问题。

 

 

1.为什么会有事件分发机制?

android的布局结构是树形结构,这就会导致一些View可能会重叠在一起,当我们手指点击的地方在很多个布局范围之内,也就是说此时有好多个布局可以响应我们的点击事件,这个时候该让哪个view来响应我们的点击事件呢?这就是事件分发机制存在的意义。

2.View中为什么会有dispatchTouchEvent方法,它存在的意义是什么?

View可以注册很多监听事件触摸事件,单击事件,长按事件等,而且view也有自己的onTouchEvent方法通过dispatchTouchEvent 来调度管理这些监听。

3.当两个或多个view重叠时,事件该如何分配?

当view重叠时,一般会显示到最上面的view

4.滑动冲突解决方式?冲突类型 外部和内部滑动方向不一致 外部和内部滑动方向一致 前两种嵌套的模式。这个是面试上的考点

解决滑动冲突的方式一般有两种,一个是外部拦截法一个是内部拦截法

  • 外部拦截法指点击事件首先都会经过父容器的拦截处理,父容器如果需要此事件就进行拦截,如果不需要此事件就不进行拦截,这样就可以解决滑动冲突问题。
  • 内部拦截法 —— 所有事件都传递给子元素,如果子元素需要就消耗掉,不需要就交给父元素处理。

有的时候面试官会问两种嵌套模式下的解决方式,可以根据具体的要求来解决对应不同的滑动冲突问题。

5.如果某个view 处理事件的时候 没有消耗down事件 会有什么结果?

在down事件来的时候 他的onTouchEvent返回false, 那么这个down事件 所属的事件序列 就是他后续的move 和up 都不会给他处理了,全部都给他的父view处理。

6.如果view 不消耗move或者up事件 会有什么结果?

那这个事件所属的事件序列就消失了,父view也不会处理的,最终都给activity 去处理了。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值