Android事件分发机制的探索与发现之Activity篇

版权声明:本文来自门心叼龙的博客,属于原创内容,转载请注明出处:https://blog.csdn.net/geduo_83/article/details/90145083

github源码下载地址:https://github.com/geduo83/android-touch-event
Android事件分发机制的探索与发现之View篇
Android事件分发机制的探索与发现之ViewGroup篇
Android事件分发机制的探索与发现之Activity篇
Android事件分发机制的探索与发现之总结篇
Android事件分发机制在实战开发中的应用之一
Android事件分发机制在实战开发中的应用之二

前两篇我们主要研究了,View和ViewGourp的事件分发流程,今天我们主要来研究一些Activity的事件传递 流程。

实际上,当我们手指触摸屏幕的时候,事件最先是传递给当前的Actvity,由Actvity的dispatchTouchEvent方法来分发事件,而Actvity会将事件传递给Window对象来分发,Window对象再传递给Decor View,而Decor View则是我们在Actvity中通过setContentView后所设置的布局的父容器

Activity dispatchTouchEvent源码:

public boolean dispatchTouchEvent(MotionEvent ev) {
        if (ev.getAction() == MotionEvent.ACTION_DOWN) {
            onUserInteraction();
        }
        if (getWindow().superDispatchTouchEvent(ev)) {
            return true;
        }
        return onTouchEvent(ev);
    }

当ACTION_DOWN事件的时候,会先执行onUserInteraction();而onUserInteraction()方法是个空方法,事实上,当此activity在栈顶时,我们触屏、点击、或者按home,back,menu键等都会触发此方法,所以onUserInteraction()可以用于屏保。

接下来调用getWindow().superDispatchTouchEvent(ev)去分发事件,如果最终事件被消耗了,则直接返回true,否则Activity才会调用onTouchEvent方法自己来处理事件。
getWindow()是一个window对象。而Window类是抽象类,从Window类的注释里面说明了PhoneWindow类是Window类的唯一实现类。然而PhoneWindow存在于框架层中,在sdk中是没有源码的,因此我们看不到。想要查看源码则必须手动关联PhoneWindow,请读者自行百度。

PhoneWindow类的superDispatchTouchEvent方法源码如下:

@Override
public boolean superDispatchTouchEvent(MotionEvent event) {
  return mDecor.superDispatchTouchEvent(event);
}

说明window对象是把事件传给mDecor去分发,mDecor就是上面我们说的Decor View。Decor View的superDispatchTouchEvent源码如下:

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

其实也是调用ViewGroup类的dispatchTouchEvent方法。
到了这里,我们已经验证了事件的传递是:Activity->Window->decor View->ViewGroup
其实到了Decor View这里就相当于事件传递到了我们在Activity中设置的布局父容器了

MainActivity的dispatchTouchEvent方法

  • 情况1:调用了父类的同名方法
@Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        Log.v(TAG,"MainActivity dispatchTouchEvent start:"+MotionEventUtil.getMotionEventName(ev));
        return super.dispatchTouchEvent(ev);
    }

测试结果:

V/MYTAG: MainActivity dispatchTouchEvent start:ACTION_DOWN
V/MYTAG: MyLayout dispatchTouchEvent start:ACTION_DOWN
V/MYTAG: MainActivity dispatchTouchEvent start:ACTION_UP
V/MYTAG: MyLayout dispatchTouchEvent start:ACTION_UP

情况2:返回true

 @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        Log.v(TAG,"MainActivity dispatchTouchEvent start:"+MotionEventUtil.getMotionEventName(ev));
        return true;
    }

测试结果:

V/MYTAG: MainActivity dispatchTouchEvent start:ACTION_DOWN
V/MYTAG: MainActivity dispatchTouchEvent start:ACTION_UP

自行消费了
情况3:返回false

@Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        Log.v(TAG,"MainActivity dispatchTouchEvent start:"+MotionEventUtil.getMotionEventName(ev));
        return false;
    }

测试结果:

V/MYTAG: MainActivity dispatchTouchEvent start:ACTION_DOWN
V/MYTAG: MainActivity dispatchTouchEvent start:ACTION_UP

其实也是应该回传给父级View了,只是我们现在没有办法进行追踪测试

好了,MainActivity就dispathTouchEvent方法也就分析完毕了,调用父类的同名方法则事件继续往下级View进行分发,如果返回true或者false则进行消费掉了,无论dispathTouchEvent返回什么值MainActivity的onTouchEvent方法永远不会被调用的,除非它下级子View的dispathTouchEvent方法或者onTouchEvent方法返回false,触摸事件才能回传给我们的MainActivity的onTouchEvent方法,才能引起MainActivity的onTouchEvent方法的调用
截止目前,关于Android事件传递机制的探索与发现,三篇文章我们就全部将完了

你可能感兴趣的:(View事件分发)