View->消费事件
我们以Activity中的Button按钮为例,我们点击按钮时有两种情况,一种就是OnTouchListener和OnClickListener,点击按钮时,我们会先执行View.java中的dispatchTouchEvent(MotionEvent event)方法进行事件分发,这个方法里面会进行判断,源码如下:
public boolean dispatchTouchEvent(MotionEvent event) {
/**
* 判断touch事件是否安全
*/
if (onFilterTouchEventForSecurity(event)) {
...
//noinspection SimplifiableIfStatement
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;
}
}
第一步:这里的判断条件有四个,一个个看,首先是li != null, mListenerInfo是在Activity的点击监听里面进行赋值的
btnBtn.setOnTouchListener(this);
由按钮实现View.java的setOntouchListener,对mListenerInfo进行了赋值
public void setOnTouchListener(OnTouchListener l) {
getListenerInfo().mOnTouchListener = l;
}
为什么说这里进行了赋值,我们再往深一点看,看到这里,就可以确定只要我们在Activity中设置了点击事件,那么li != null就一定为true
@UnsupportedAppUsage
ListenerInfo getListenerInfo() {
if (mListenerInfo != null) {
return mListenerInfo;
}
mListenerInfo = new ListenerInfo();
return mListenerInfo;
}
第二步:我们回到第一步里面,还有三个判断条件,现在我们看第二个
li.mOnTouchListener != null,因为我们在Activity中的设置点击事件时的代码如下
btnBtn.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
Log.i("jett", "onTouch: ");
return false;
}
});
因为我们new 了一个View.OnTouchListener(),所以li.mOnTouchListener != null为true,
第三步:(mViewFlags & ENABLED_MASK) == ENABLED这个条件的意思是按钮可以点击,enable表示按钮默认可以点击,所以如果是按钮的话,这里条件默认也是true,那么就只剩最后一个条件,前面三个条件恒成立,那么就是最后一个条件影响着result返回值
li.mOnTouchListener.onTouch(this, event))
可以看到,这里的话就是一个onTouch(this,event)方法,这个onTouch(this,event)的返回值在Activity回调的时候我们自己设置
btnBtn.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
Log.i("jett", "onTouch: ");
return false;
}
});
可以看到我们设置的是一个false,所以
if (!result && onTouchEvent(event)) {
result = true;
}
result的值直接影响OnTouchEvent(event)的执行,因为我们return false,所以,我们执行onTouchEvent(event),看一下源码,这里面就有
MotionEvent.ACTION_UP、按钮按下
MotionEvent.ACTION_DOWN、按钮抬起
MotionEvent.ACTION_MOVE、按住滑动
MotionEvent.ACTION_CANCEL、取消
点击事件是在
MotionEvent.ACTION_UP这个case里面执行的,所以我们看下源码
switch (action) {
case MotionEvent.ACTION_UP:
...
if (!mHasPerformedLongPress && !mIgnoreNextUpEvent) {
// This is a tap, so remove the longpress check
removeLongPressCallback();
// Only perform take click actions if we were in the pressed state
if (!focusTaken) {
// Use a Runnable and post this rather than calling
// performClick directly. This lets other visual state
// of the view update before click actions start.
if (mPerformClick == null) {
mPerformClick = new PerformClick();
}
if (!post(mPerformClick)) {
performClickInternal();
}
}
}
点击事件在这个new PerformClick();开始进入,到performClickInternal(),返回performClick()
public boolean performClick() {
// We still need to call this method to handle the cases where performClick() was called
// externally, instead of through performClickInternal()
notifyAutofillManagerOnClick();
final boolean result;
final ListenerInfo li = mListenerInfo;
if (li != null && li.mOnClickListener != null) {
//点击声音的处理
playSoundEffect(SoundEffectConstants.CLICK);
li.mOnClickListener.onClick(this);
result = true;
} else {
result = false;
}
sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED);
notifyEnterOrExitForAutoFillIfNeeded(true);
return result;
}
根据前面所说,li != null 是一定成立的,所以点击事件能否执行,取决于li.mOnClickListener != null,而这个条件又取决于我们是否在Activity中是否设置了点击监听事件。
btnBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Log.i("jett", "onClick: ");
}
});
然后就是根据这个执行流程,我们可以分析出,
1、OnTouch,OnTouchEvent,OnClick的一个执行顺序是OnTouch -> OnTouchEvent -> OnClick
2、OnTouchEvent不是一定执行的,它能否执行取决于result的值,是为true还是false,也就是取决于OnTouch能否执行,进一步也就是是否设置了点击事件,同时还要判断是否默认为可点击状态enable,如:imageView,它就是默认不可点击的。
以上就是View->消费事件的一个流程的个人学习总结,如有错误,还请大佬多多指正,流程图我是画不出来了=。=,