第15天 Android Touch事件学习 2 触发点击事件的地方



     本篇是在上一篇的基础上讨论《Touch事件学习 1 点击事件》, 不过例子非常简单只是一个引子,走出事件学习的第一步也通常是学习Android开发第一个基础到的涉及事件的例子。现在接着来从Andorid的源码的角度分析一下点击事件的原理,这里的源码是基于Android 4.0(即Andorid 14)。

    之前也编译过Android的源码生成zip文件并且刷到手机上,但是之后重装系统源码也没有保留全部格式化了,并且再完整下载Andorid源码比较耗时耗力,最重要的是也没有必要。这里使用Android 4.0是因为Android SDK Manager中可以很容易的通过勾选“Sources for Andorid SDK” 获取此版本的源码,因为其提供最低版本的是Android 4.0这里就基于这一版进行分析。如果想更省事一些也可以直接通过在线方式源码,地址是:http://grepcode.com/ 直接搜索android可以在线查看所有版本的Android源码并且可以进行比较,但我个人还是比较喜欢通过IDE查看本地代码。


一、点击事件相关源码追踪

1. 从上一篇文章的例子中可以看出,仅调用了一个方法即view.setOnClickListener,这里就从View类的setOnClickListener方法开始查看

    /**
     * Register a callback to be invoked when this view is clicked. If this view is not
     * clickable, it becomes clickable.
     *
     * @param l The callback that will run
     *
     * @see #setClickable(boolean)
     */
    public void setOnClickListener(OnClickListener l) {
       // 先判断是否可以点击
        if (!isClickable()) {
            // 如果不能点击,这里重置为可点击
            setClickable(true);
        }
        // 把内部类参数复制给内部变量
        mOnClickListener = l;
    }



2. mOnClickListener何处调用?

从上面看到了setOnClickListener会初始化mOnClickListener内部变量,那何处会调用mOnClickListener呢?通过在View类中查找可以发现

    /**
     * Call this view's OnClickListener, if it is defined.
     *
     * @return True there was an assigned OnClickListener that was called, false
     *         otherwise is returned.
     */
    public boolean performClick() {
        // 发送一个给定的可访问性的点击事件类型。
        sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED);

        if (mOnClickListener != null) {
            // 播放点击音效
            playSoundEffect(SoundEffectConstants.CLICK);
            // *重点* 触发内部类中的onClick方法
            mOnClickListener.onClick(this);
            return true;
        }

        return false;
    }

   现在已经找到了哪段代码执行setOnClickListener内部类的onClick方法,那何处调用performClick触发执行点击事件呢?接着通过performClick查找何处调用了此方法


3. 何处的调用执行点击事件?

    通过在View类中查找performClick可以发现onKeyUp 与 onTouchEvent 两处调用,如果有些Android基础的话可以看出onKeyUp通常是点击物理键(例如:后退键、Home键)时触发,而之前的例子是手指点击触发的所以排除onKeyUp,先下面仅看onTouchEvent


4. 点击事件的触发根源onTouchEvent

    /**
     * Implement this method to handle touch screen motion events.
     *
     * @param event The motion event.
     * @return True if the event was handled, false otherwise.
     */
    public boolean onTouchEvent(MotionEvent event) {
		......

        if (((viewFlags & CLICKABLE) == CLICKABLE ||
                (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE)) {
            switch (event.getAction()) {
                case MotionEvent.ACTION_UP:
                    ......

                    // 点击事件最终处理的地方
                    if (mPerformClick == null) {
	                    mPerformClick = new PerformClick();
                    }
                    if (!post(mPerformClick)) {
	                    performClick();
                    }

                    ......
                    }
                    break;

            }
            return true;
        }

        return false;
    }


    上面仅仅贴出的是onTouchEvent与点击事件关联的代码,因为此方法中代码太多,避免干扰仅贴出了核心的几行伪代码。可以得出一个简单的结论是在onTouchEvent中调用执行点击事件执行代码的。


二、分析点击事件流程

    上面是通过查看源码右下至上一步步查找,找出点击事件触发的地方,但是代码具体执行的时候肯定是由上至下来执行的,而且按照执行的流程来分析也比较容易理解,但是可能还有一个疑问什么地方调用并执行的onTouchEvent?发现并提出问题是一个很好的习惯的,但是这里先知道onTouchEvent是最终处理点击事件的地方就可以了,学习是一点点来的,之后会总结这里这个问题,现在这个问题先搁置一下。

    现在从分析源码反向也是代码执行的流程看下

1. 如果手指点击屏幕,Android系统会先触发执行onTouchEvent方法

2. 从case MotionEvent.ACTION_UP 可以看出当手指抬起时触发performClick()方法

3. performClick方法中会调用mOnClickListener.onClick(this);

4. mOnClickListener变量是在setOnClickListener方法中进行初始化

5. 触发执行setOnClickListener内部类中的代码,按上一篇的例子是弹出“点击图片”文字


     当然这里仅仅是简单说下点击事件流程,并没有详细展开介绍,目的是先为了引出所有事件处理的最终方法View.onTouchEvent.。


三、其他事件原理与onTouchEvent方法

    如果想多了解一些的话,可以看看上一篇文章提高的View提供的事件相关方方法

setOnClickListener
setOnLongClickListener  
setOnTouchListener  
   这里仅仅跟踪了setOnClickListener方法,有兴趣可以跟踪下其他几个方法都何处调用的。


    如果比较懒一点不想自己查也没关系,上面三个方法最终都是在onTouchEvent中进行处理,所以此方法是Android处理所有事件的最终的方法,包括上面看到的点击事件、长按事件,包括之后会学习的各种手势(例如:滚动、Fling、轻触等)都是在此方法中进行手势的判断。




触摸事件学习系列文章详见:

《Android Touch事件学习系列汇总》



你可能感兴趣的:(第15天 Android Touch事件学习 2 触发点击事件的地方)