美文网首页Android杂货铺Android开发Android知识
OnClickListener.onClick是在View的哪里

OnClickListener.onClick是在View的哪里

作者: 一个不熬夜的孩子 | 来源:发表于2017-02-07 23:45 被阅读216次

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();
    }
}

上面的代码是ViewonTouchEvent()switch语句中UP的一段代码,最关键的是post()这个方法,他的文档写的很清楚,就是将这个PerformClickRunnable对象放入到当前线程的消息队列中。所以我们的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()里面,所以这里就不列出来了。

相关文章

网友评论

    本文标题:OnClickListener.onClick是在View的哪里

    本文链接:https://www.haomeiwen.com/subject/uytvittx.html