美文网首页
(三)Android事件分发机制 - Activity篇

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

作者: DevWang | 来源:发表于2017-08-29 10:01 被阅读0次

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

    当一个点击操作发生时,事件最先传递给当前的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篇

          本文链接:https://www.haomeiwen.com/subject/puyndxtx.html