OnClickListener.onClick是在View的哪里调用的
我们在View的源码中可以很快的找到performClick()
这个方法:
public boolean performClick() {
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);
return result;
}
那么这个方法是在哪里调用的呢,回想一下,Android的事件机制是先从dispatchTouchEvent()
到onTouchEvent()
的,performClick()
在onTouchEvent()
出现过,我们来看看onTouchEvent()
方法部分源码:
if (!focusTaken) {
if (mPerformClick == null) {
mPerformClick = new PerformClick();
}
if (!post(mPerformClick)) {
performClick();
}
}
上面的代码是View
的onTouchEvent()
在switch
语句中UP
的一段代码,最关键的是post()
这个方法,他的文档写的很清楚,就是将这个PerformClick
的Runnable
对象放入到当前线程的消息队列中。所以我们的performClick()
通常是将PerformClick
这个Runnable
对象放入到消息队列,然后在Looper
中取出来调用的。但是会有一种特殊情况是保存到消息队列的时候失败,那么就不处理这个Event
了吗,所以在上面的代码中,判断post()
的返回值,如果失败,那么就在onTouchEvent()
方法中直接调用performClick()
方法。
下面是post()方法的文档和源码:
/**
* <p>Causes the Runnable to be added to the message queue.
* The runnable will be run on the user interface thread.</p>
*
* @param action The Runnable that will be executed.
*
* @return Returns true if the Runnable was successfully placed in to the
* message queue. Returns false on failure, usually because the
* looper processing the message queue is exiting.
*
* @see #postDelayed
* @see #removeCallbacks
*/
public boolean post(Runnable action) {
final AttachInfo attachInfo = mAttachInfo;
if (attachInfo != null) {
return attachInfo.mHandler.post(action);
}
// Postpone the runnable until we know on which thread it needs to run.
// Assume that the runnable will be successfully placed after attach.
getRunQueue().post(action);
return true;
}
但是通过源码可以看出,OnClickListener的onClick是通过消息队列调用的,可是OnTouchListener的onTouch是直接调用的。由于onTouch的代码比较好找,就在dispatchTouchEvent()
里面,所以这里就不列出来了。