Android事件分发机制源码剖析(1)——Activity对点击事件的分发过程

点击事件用MotionEvent表示,当一个点击操作发生时,事件最先传递给当前的Activity,由Activity得dispatchTouchEvent来进行事件派发,具体的工作由Activity内部的Window来完成。Window会将事件传递给DecorView,DecorView一般就是当前页面的顶层容器(即setContentView所设置的View的父容器),通过Acitivty#getWindow().getDecorView()可以获得。Activity的dispatchTouchEvent源码如下:

Activity#dispatchTouchEvent

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

分析一下上面的代码,首先事件开始交给Acitivty所附属的Window进行分发,如果返回true,整个事件循环就结束了,返回false意味着事件没人处理,所有View的onTouchEvent都返回了false,那么Activity的onTouchEvent就会被调用。

接下来看Window是如何将事件传递给ViewGroup的。通过源码我们知道,Window是个抽象类,而Window的superDispatchTouchEvent方法也是个抽象方法,因此我们必须找到Window的实现类。

然后,我们很容易就会发现Window的实现类就是PhoneWindow,那么PhoneWindow是如何处理事件的呢?

PhoneWindow#superDispatchTouchEvent

public boolean superDispatchTouchEvent(MotionEvent ev){
    return mDecor.superDispatchTouchEvent(ev);
}

可以发现,PhoneWindow将事件直接传递给了DecorView,这个DecorView又是什么呢?

private final class DecorView extends FrameLayou implements RootViewSurfaceTaker //This is the top-level view of window,containing the window decor. private DecorView mDecor;

publiv final View getDecorView(){
    if(mDecor==null){
        installDecor();
    }
    return mDecor;
}

我们知道,通过((ViewGroup)getWindow().getDecorView().findViewById(android.R.id.content)).getChildAt(0)这种方式就可以获取Activity所设置的View,这个mDecor显然就是getWindow().getDecorView()返回的View,而我们通过setContentView设置的View是它的一个子View。目前事件传递到了DecorView这里,由于DecorView继承自FrameLayout且是父View,所以最终事件就会传递给View。换句话说,事件肯定会传递到View,不然应用怎么响应点击事件呢?分析到这里,事件已经传递给顶级的View了,即在Activity中通过setContentView设置的View,另外顶层View也叫根View,顶层View一般来说都是ViewGroup。

至此,Activity对点击事件的分发过程已经介绍完毕,有关事件在ViewGroup和View中的传递过程请关注后面的博文。

你可能感兴趣的:(Activity,事件分发,分发,点击事件)