android中的事件传递机制(1)

最近由于项目的需要博主研究了一下事件传递机制,在网上翻阅了很多的解释,看的也是云里雾里的,不过经过梳理和观察源码终于把事件传递机制研究明白了

将分为三部分博客来记录android事件传递机制
在写之前推荐几个比较好的事件传递机制的博客,有助于大家理解
1.关于view什么时候会调用onClick和ontouch监听事件
2事件传递和消费(不过这个博客写的有部分错误,博主将会在后面给大家解释哪里出现错误)
3事件的三种类型和调用顺序(文章中有部分问题,仅用于更好的理解后面内容)

前言:如果对事件传递没有一点了解的建议先看一下1和2的微博,如果有所了解的人可直接看本文,肯定让你深刻的理解事件传递

看过了这么多文字想必你还是有点蒙的,而且很多文章都是相互冲突的,所以我们最好的办法就是去看源码.
1.首先我先分析一下android中的控件的结构,
activity作为一个活动中包含一个window窗口,window下可以放多个ViewGroup,viewGroup中可以放多个view
2.但是我们通过源码可以看出ViewGroup也是继承View的

public abstract class ViewGroup extends View implements ViewParent, ViewManager {

3.那我就从view开始看起,通过看源码可以发现view中包含两个处理时间的方法,
dispatchTouchEvent(MotionEvent event)onTouchEvent(MotionEvent event)
4.我们知道事件传递机制都是先调用dispatchTouchEvent()方法,所有我们看一下源码

   public boolean dispatchTouchEvent(MotionEvent event) {
        if (event.isTargetAccessibilityFocus()) {
            if (!isAccessibilityFocusedViewOrHost()) {
                return false;
            }
            event.setTargetAccessibilityFocus(false);
        }

        boolean result = false;

        if (mInputEventConsistencyVerifier != null) {
            mInputEventConsistencyVerifier.onTouchEvent(event, 0);
        }

        final int actionMasked = event.getActionMasked();
        if (actionMasked == MotionEvent.ACTION_DOWN) {
            stopNestedScroll();
        }

        if (onFilterTouchEventForSecurity(event)) {
            ListenerInfo li = mListenerInfo;
            if (li != null && li.mOnTouchListener != null
                    && (mViewFlags & ENABLED_MASK) == ENABLED
                    && li.mOnTouchListener.onTouch(this, event)) {
                result = true;
            }

            if (!result && onTouchEvent(event)) {
                result = true;
            }
        }

        if (!result && mInputEventConsistencyVerifier != null) {
            mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
        }
        if (actionMasked == MotionEvent.ACTION_UP ||
                actionMasked == MotionEvent.ACTION_CANCEL ||
                (actionMasked == MotionEvent.ACTION_DOWN && !result)) {
            stopNestedScroll();
        }

        return result;
    }

前几行是关于判读view是否有焦点的代码我们不用看,主要看其中这段代码

 if (li != null && li.mOnTouchListener != null
                    && (mViewFlags & ENABLED_MASK) == ENABLED
                    && li.mOnTouchListener.onTouch(this, event)) {
                result = true;
            }

            if (!result && onTouchEvent(event)) {
                result = true;
            }

从这段代码中可以看的出来view是先判读用户是否绑定了OnTouchListener,如果绑定了则调用用户定义的onTouch方法,并且把返回值作为最终结果返回。如果没有定义就调用view中的onTouchEvent方法并返回结果。(在onTouch方法中会调用点击事件处理)
5.看过view的代码你应该知道了view中dispatchTouchEvent()onTouchEvent()的关系了吧,是前者调用了后者。
6.接下来我们看一下ViewGroup中的代码,这个要比view要复杂一些,通过看源码我们可以看出来ViewGroup继承View并且重写了
dispatchTouchEvent()
;和增加了OnInterceptTouchEvent();
7.还是首先我们看一下dispatchTouchEvent()中的代码
由于该方法的代码过长我就不粘贴了,大家可以看自己的android源码,在第1929行就是该方法,这个方法先是在1960行调用了
onInterceptTouchEvent
方法,并记录返回值intercepted ,如果intercepted==flase那么将调用ViewGroup中的所有子View的dispatchTouchEvent()。一但有某一个view的方法返回true则ViewGroup的dispatchTouch()返回true。
8.从这一点我们就能知道了onInterceptTouchEvent是怎么进行屏蔽的了,onInterceptTouchEvent返回为true时则不会调用子view的dispatchTouch,只调用viewGroup的super.onTouchEvent()。
9.那么什么时候viewGroup的子view的dispatchTouch()会返回true?刚才我们在看view的代码的时候知道,当view中的onTouchEvent返回true时分发函数也会返回true。
10.从这些代码中我们就能理解了,时间是如何向下传递的了。那么如果没有子view呢?在2372行代码中我们能知道,如果没有子view则ViewGroup调用super.dispatchTouch()

注:viewGroup中的onInterceptTouchEvent默认返回的是false,也就是默认是都要给子view进行事件传递的,但是有些继承了viewGroup并且重写了该方法的就要具体问题具体分析了。

下一期我讲述事件传递到最低端后是否会回传给上层控件

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值