View类中存在一个static的ListenerInfo类
在ListenerInfo内部定义多个Listener成员变量
a)分析OnClickListener
public OnClickListener mOnClickListener;
OnClickListener 是一个接口
public interface OnClickListener{
void onClick(View v);
}
我们在使用View时,通常会通过finViewById等方式获取到View的实例后
为该View设置click的监听
view.setOnClickListener( OnClickListener listener)
一般有两种方式:
1)一种直接定义匿名内部类,new 一个OnClickListener
2)在当前类中实现interface OnClickListener
那么view的click事件是怎样回调到OnClickListener的onClick方法的
分析流程:
onClick方法的调用是在View的onTouchEvent方法中
当MotionEvent为ACIONT_UP时会调用到performClick()方法
performClick方法具体:
public boolean performClick() {
final boolean result;
final ListenerInfo li = mListenerInfo;
if (li != null && li.mOnClickListener != null) {
playSoundEffect(SoundEffectConstants.CLICK);
li.mOnClickListener.onClick(this);// 这里就回调到了onClick方法
result = true;
} else {
result = false;
}
sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED);
return result;
}
看代码可知道,要调用到onClick方法的条件有很多,首先子View没有重写onTouchEvent,
或者重写了但是没有ACTION_UP没有消费掉,都会调到onClick方法
b) 分析OnTouchListener
同理给View设置监听setOnTouchListener(OnTouchListener l)
public interface OnTouchListener {
boolean onTouch(View v , MotionEvent event)
}
回调到onTouch方法的流程分析:
view事件的分发流程,当执行到ViewGroup.dispatchTouchEvent->找到子view调用dispatchTransformedTouchEvent进行具体
的分发->会调用到View的dispatchTouchEvent方法
在View.dispatchTouchEvent方法可以看到如下逻辑:
if (onFilterTouchEventForSecurity(event)) {
if ((mViewFlags & ENABLED_MASK) == ENABLED && handleScrollBarDragging(event)) {
result = true;
}
//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;
}
}
可以知道当给当前的View设置了OnTouchListener时就会优先处理OnTouchListener中的onTouch方法,如果onTouch返回true
表示已经消费了该事件不用进行后续处理。否者就会直接跳转到onTouchEvent方法中处理后续逻辑
c)分析OnDragListener
public interface OnDragListener{
boolean onDrag(View v , DragEvent event);
}
流程分析:
dispatchDragEvent->callDragEventHandler->
setOnDragListener如果设置了监听那么会先判断OnDragListener.onDrag是否消费事件,
如果没有消费那么就执行View本身的onDragEvent方法