Android 事件传递总结

来源:互联网 发布:c语言在线运行 编辑:程序博客网 时间:2024/06/08 13:44

Android 事件传递总结

首先 吐槽下17年的北京市场,简直无法生存了,为了18年不被淘汰,只能不停的催眠自己,我爱学习,我爱钻研,我更爱撸代码:

  • 参考郭神的博客 Android事件分发机制完全解析,带你从源码的角度彻底理解
  • View的事件分发处理过程
  • ViewGroup 的事件分发过程

View事件分发过程详解

首先单独给一个View添加一个点击事件一般我们使用

button.setOnClickListener(new OnClickListener() {      @Override      public void onClick(View v) {          Log.d("TAG", "onClick execute");      }  }); 

或者还可以使用setOnTouchListener方法

    button.setOnTouchListener(new OnTouchListener() {          @Override          public boolean onTouch(View v, MotionEvent event) {              Log.d("TAG", "onTouch execute, action " + event.getAction());              return false;          }      });  

现在,给一个控件,添加了两次监听事件。
onTouch是优先于onClick执行的,并且onTouch执行了两次,一次是ACTION_DOWN,一次是ACTION_UP(你还可能会有多次ACTION_MOVE的执行,如果你手抖了一下)。因此事件传递的顺序是先经过onTouch,再传递到onClick。
并且 onTouch方法是有返回数据的。现在我默认返回的是false,如果我把此方法返回的数据为 true, 那么onlick方法并不会执行。

只要你触摸到了任何一个控件,就一定会调用该控件的dispatchTouchEvent方法。那当我们去点击按钮的时候,就会去调用View类里的dispatchTouchEvent方法
    public boolean dispatchTouchEvent(MotionEvent event) {          if (mOnTouchListener != null && (mViewFlags & ENABLED_MASK) == ENABLED &&                  mOnTouchListener.onTouch(this, event)) {              return true;          }          return onTouchEvent(event);      }  

源码中,dispatchTouchEvent 会走一个判断,

判断为true的话,dispatchTouchEvent方法会返回 true,
如果判断走flase的话,会执行 onTouchEvent(event)方法

一共是三个判断,我们一个一个分析、
第一个判断:mOnTouchListener != null

    public void setOnTouchListener(OnTouchListener l) {          mOnTouchListener = l;      }  

看到源码,在我们给一个view添加点击事件的时候mOnTouchListener就被赋值了,此判断为true

第二个判断:(mViewFlags & ENABLED_MASK) == ENABLED
这个是 判断当前点击的控件是否是enabled ,因为所有的控件默认为enabled(是否可点击),所以这个恒定为true;

第三个判断: mOnTouchListener.onTouch(this, event)
其实就是去回调控件注册touch事件时的onTouch方法。也就是说如果我们在onTouch方法里返回true,就会让这三个条件全部成立,从而整个方法直接返回true。如果我们在onTouch方法里返回false,就会再去执行onTouchEvent(event)方法。

结论:
首先在dispatchTouchEvent中最先执行的就是onTouch方法,因此onTouch肯定是要优先于onClick执行的,而如果在onTouch方法里返回了true,就会让dispatchTouchEvent方法直接返回true,不会再继续往下执行。而打印结果也证实了如果onTouch返回true,onClick就不会再执行了。

所以我们可以判断出,onClick的执行肯定在onTouchEvent(event)方法中

写到这里,一个View的事件传递流程,应该很清楚了。

面试:
1. onTouch和onTouchEvent有什么区别?

从源码中可以看出,这两个方法都是在View的dispatchTouchEvent中调用的,onTouch优先于onTouchEvent执行。如果在onTouch方法中通过返回true将事件消费掉,onTouchEvent将不会再执行。

ViewGroup事件分发过程详解

当你点击了某个控件,首先会去调用该控件所在布局的dispatchTouchEvent方法,然后在布局的dispatchTouchEvent方法中找到被点击的相应控件,再去调用该控件的dispatchTouchEvent方法。
这是整个事件传递的过程

ViewGroup事件分发过程详解


1 0