(三)Android事件分发机制 - Activity篇

本文适用于对Android事件分发机制有一定基础的开发者阅读,主要是通过对Activity类中的事件分发、事件消费的源代码进行解析以达到完全理解其原理的目的

  • (一)Android事件分发机制 - View篇
  • (二)Android事件分发机制 - ViewGroup篇
  • (三)Android事件分发机制 - Activity篇
  • (四)Android事件分发机制 - 总结篇

当一个点击操作发生时,事件最先传递给当前的Activity,由ActivitydispatchTouchEvent来进行事件的分发,接下来我们通过源代码(基于Android6.0)看看这个方法内部到底做了哪些事情。

1、Activity#dispatchTouchEvent源码解析

public boolean dispatchTouchEvent(MotionEvent ev) {
    if (ev.getAction() == MotionEvent.ACTION_DOWN) {
        onUserInteraction();
    }
    if (getWindow().superDispatchTouchEvent(ev)) {
        return true;
    }
    return onTouchEvent(ev);
}
  • 首先判断MotionEvent是不是ACTION_DOWN,如果是的话,执行onUserInteraction()方法:

      // 空方法,让子类实现
      public void onUserInteraction() {
          // 当此activity在栈顶时,触屏点击按home,back,menu键等都会触发此方法。
          // 下拉statubar、旋转屏幕、锁屏不会触发此方法
          // 所以它会用在屏保应用上,因为当你触屏机器 就会立马触发一个事件,而这个事件又不太明确是什么,正好屏保满足此需求。
      }
    
  • getWindow()会返回PhoneWindow对象(PhoneWindow类是Window抽象类的唯一实现子类),调用PhoneWindow#superDispatchTouchEvent(ev):

      @Override
      public boolean superDispatchTouchEvent(MotionEvent event) {
          return mDecor.superDispatchTouchEvent(event);
      }
    
  • mDecor是DecorView的实例,是视图的顶层View。DecorView继承自FrameLayout,那么它的父类就是ViewGroup了,而super.dispatchTouchEvent(event)方法,其实就应该是ViewGroup的dispatchTouchEvent()方法

      // This is the top-level view of the window, containing the window decor.
      private DecorView mDecor;
    
      public class DecorView extends FrameLayout implements RootViewSurfaceTaker, WindowCallbacks {
          ...
      }
    

小结
  • 当一个点击操作发生时,事件的传递顺序为:Activity -> Window -> DecorView,DecorView一般就是当前界面的底层容器(即setContentView所设置的View的父容器)

2、Activity#onTouchEvent源码解析

public boolean onTouchEvent(MotionEvent event) {
    if (mWindow.shouldCloseOnTouch(this, event)) {
        finish();
        return true;
    }
    return false;
}
shouldCloseOnTouch
public boolean shouldCloseOnTouch(Context context, MotionEvent event) {
    // 判断mCloseOnTouchOutside标记及是否为ACTION_DOWN事件
    // 同时判断event的x、y坐标是不是超出Bounds,
    // 然后检查DecorView是否为空
    if (mCloseOnTouchOutside && event.getAction() == MotionEvent.ACTION_DOWN
            && isOutOfBounds(context, event) && peekDecorView() != null) {
        return true;
    }
    return false;
}
小结
  • 一个点击操作要是没有被Activity下的任何View处理,即顶层DecorViewdispatchTouchEvnent()方法返回false的话,则ActivityonTouchEvent()方法会被调用。

你可能感兴趣的:((三)Android事件分发机制 - Activity篇)