事件分发是作为一名Android开发者必须要掌握的东西,下面我们来一起探究下是如何进行事件分发的


首先我们要搞明白,什么是事件分发?Android中的视图是由一个个View嵌套构成的层级视图,即一个View里包含有子View,而这个子View里面又可以再添加View。当用户触摸屏幕产生一系列事件时,事件会由高到低,由外向内依次传递,最终把事件交到一个具体的View手上处理,这个传递的过程就叫做事件分发。


事件分发的顺序 Activity->ViewGroup->View 

 

  支持事件分发的方法dispatchTouchEvent、onInterceptTouchEvent、onTouchEvent 

 

  下面我们先来探究下事件分发的顺序 

 

  当手机屏幕发生了点击事件时,首先调用的是Activity的dispatchTouchEvent方法,起主要代码如下: 

 

  if (getWindow().superDispatchTouchEvent(ev)) { 

 

              return true; 

 

          } 

 

  return onTouchEvent(ev); 

 

    

 

  调用了getWindow().superDispatchTouchEvent(ev)方法, 

 
public
 
return mWindow;
 
}


getWindow方法返回了一个Window对象,这个Window对象是一个抽象类,他的唯一实现是PhoneWindow,你说我是怎么知道的?上注释




android 分发机制事件 安卓的事件分发_java


 


好的我们在去PhoneWindow中看下superDispatchTouchEvent方法,源码是在frameworks层。路径


.frameworks/base/core/java/com/android/internal/policy/PhoneWindow.java 

 

  // This is the top-level view of the window, containing the window decor. 

 

     private DecorView mDecor; 

 

     public boolean superDispatchTouchEvent(MotionEvent event) { 

 

          return mDecor.superDispatchTouchEvent(event); 

 

      }

到这里发现了DecorView,干啥的呢?注释说明的很清楚,他是window的顶层视图


我们在去DecorView中看下superDispatchTouchEvent方法


public  boolean  superDispatchTouchEvent  (MotionEvent event) { 
 return  super  .dispatchTouchEvent(event); }


调用了父类的dispatchTouchEvent, DecorView extends FrameLayout,有的人说我怎么在FrameLayout中找不到这个方法呢,是的我也找不到为啥呢?FrameLayout extends ViewGroup,明白了吧,我们直接去ViewGroup中看看有没有


代码太多就不放了,路径在android.view下


在ViewGroup中的  dispatchTouchEvent方法默认访问了onInterceptTouchEvent
 
// Check for interception.
 
final boolean
 
intercepted = onInterceptTouchEvent(ev);
 
然后调用了dispatchTransformedTouchEvent并传递了四个参数,注意第三个参数是null
 
// No touch targets so treat this as an ordinary view.
 
handled = dispatchTransformedTouchEvent(ev, canceled, null,
 
TouchTarget.ALL_POINTER_IDS);
 
在 dispatchTransformedTouchEvent方法中,第三个参数是child,看看child==null时做了什么操作
 
private boolean dispatchTransformedTouchEvent(MotionEvent event, boolean
 
View child, int
 

    

 
if (child == null) {
 
handled = super.dispatchTouchEvent(event);
 
} else
 
handled = child.dispatchTouchEvent(event);
 
}


child是null时,调用了父类的dispatchTouchEvent方法,我们在接着往下看ViewGroup extends View,


直接看View中的dispatchTouchEvent方法,在View中的dispatchTouchEvent方法中调用了自身的onTouchEvent方法,并默认返回一个false。


到这里整个事件的分发顺序我们是不是就清楚了,Activity->ViewGroup->View,老铁们,很清楚有木有!有的同学要说了View默认返回false或者有返回true的情况在然后呢,下面这些就不一一分析了,一大段的代码文字看着也烦,大家根据我这个思路自己过一遍framework源码即可,下面在给大家整体上一张事件分发流程图


 



android 分发机制事件 安卓的事件分发_android 分发机制事件_02


 


简单的总结下:


Activity收到触屏分发事件后对自己的dispatchTouchEvent说,你给我把这个事件处理下,Activity的dispatchTouchEvent收到指令不想干,他对他的小弟ViewGroup中的dispatchTouchEvent说你把这个事件处理下,ViewGroup中的dispatchTouchEvent也不想干活啊,他对自己家的onInterceptTouchEvent说,这个事件交给你,赶紧处理下,onInterceptTouchEvent也是有脾气的,你们都不干让我干,我也不干,他手下也有小弟,于是对他手下的小弟View中的dispatchTouchEvent说,这个问题你看看,是不是你们团队的搞的bug,赶紧处理下,View团队的dispatchTouchEvent于是将问题提交给了他们团队专门处理问题的onTouchEvent,onTouchEvent经过三天三夜的苦战研究发现解决不了,于是上报给了ViewGroup团队的onTouchEvent,ViewGroup团队的onTouchEvent接到小弟的上报问题后,发现自己也处理不了,于是又上报给了Activity团队的onTouchEvent,Activity团队的onTouchEvent接到小弟的上报问题后发现时间过去太久了,客户都不用这个系统了,直接扔一边去了爱咋地咋地吧。