View之ListenerInfo的分析

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方法

results for ""

    No results matching ""