当前位置:  编程技术>移动开发

详细介绍Android中回调函数机制

    来源: 互联网  发布时间:2014-10-22

    本文导语:  提示:在阅读本文章之前,请确保您对Touch事件的分发机制有一定的了解 在Android的学习过程中经常会听到或者见到“回调”这个词,那么什么是回调呢?所谓的回调函数就是:在A类中定义了一个方法,这个方法中用到了一个...

提示:在阅读本文章之前,请确保您对Touch事件的分发机制有一定的了解

在Android的学习过程中经常会听到或者见到“回调”这个词,那么什么是回调呢?所谓的回调函数就是:在A类中定义了一个方法,这个方法中用到了一个接口和该接口中的抽象方法,但是抽象方法没有具体的实现,需要B类去实现,B类实现该方法后,它本身不会去调用该方法,而是传递给A类,供A类去调用,这种机制就称为回调。

下面我们拿具体的Button的点击事件进行模拟分析:

首先,在View类中我们能找到setOnClickListener(OnClickListener l)方法:

代码如下:

public void setOnClickListener(OnClickListener l) {

     if (!isClickable()) {

         setClickable(true);

     }

     getListenerInfo().mOnClickListener = l;

}

可以看到,在该方法中将OnClickListener赋值给了mOnClickListener,那么我们继续向下找,会看到在performClick()方法中执行了我们实现的onClick()方法。

代码如下:

public boolean performClick() {

     sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED);

     ListenerInfo li = mListenerInfo;

     if (li != null && li.mOnClickListener != null) {

         playSoundEffect(SoundEffectConstants.CLICK);

         li.mOnClickListener.onClick(this);

         return true;

     }

     return false;

}

由此我们可以清楚的看不到,在父类中我们要用到onClick()方法,但是父类却没有去实现该方法,而是定义了一个方法setOnClickListener(OnClickListener l),如果子类想要自己能够响应点击事件,则它就必须重写父类的该方法,实现OnClickListener接口和它的onClick()方法。在子类实现该接口和方法后,将其通过参数传递给父类,在父类中执行onClick()方法。

那么,为什么会在父类中执行到该方法呢,这就要说到Android中的另一个重要的机制——触摸事件的传递机制。

我们知道,只要我们的手指触摸到手机屏幕,就一定会执行dispatchTouchEvent(MotionEvent event)方法,接下来我们就看一下dispatchTouchEvent方法中都有哪些内容:

代码如下:

public boolean dispatchTouchEvent(MotionEvent event) {

        if (mInputEventConsistencyVerifier != null) {

            mInputEventConsistencyVerifier.onTouchEvent(event, 0);

        }

 

        if (onFilterTouchEventForSecurity(event)) {

            //noinspection SimplifiableIfStatement

            ListenerInfo li = mListenerInfo;

            if (li != null && li.mOnTouchListener != null

                    && (mViewFlags & ENABLED_MASK) == ENABLED

                    && li.mOnTouchListener.onTouch(this, event)) {

                return true;

            }

 

            if (onTouchEvent(event)) {

                return true;

            }

        }

 

        if (mInputEventConsistencyVerifier != null) {

            mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);

        }

        return false;

}

这里我们不细讲Touch事件的分发机制,因为网上有哥们已经讲的很清楚了。请参看篇首提供的链接。

我们看一下第17行,由于我们没有实现OnTouchListener接口,而onTouch()方法的默认返回值为false,所以第一个if语句中的代码不会被执行到,进入第二个if语句中,执行了onTouchEvent()方法。那么我们再来看一下该方法:

代码如下:

public boolean onTouchEvent(MotionEvent event) {

        final int viewFlags = mViewFlags;

 

        if ((viewFlags & ENABLED_MASK) == DISABLED) {

            if (event.getAction() == MotionEvent.ACTION_UP

                     && (mPrivateFlags & PFLAG_PRESSED) != 0) {

                setPressed(false);

            }

            // A disabled view that is clickable still consumes the touch

            // events, it just doesn't respond to them.

            return (((viewFlags & CLICKABLE) == CLICKABLE ||

                    (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE));

        }

 

        if (mTouchDelegate != null) {

            if (mTouchDelegate.onTouchEvent(event)) {

                return true;

            }

        }

 

        if (((viewFlags & CLICKABLE) == CLICKABLE ||

                (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE)) {

            switch (event.getAction()) {

                case MotionEvent.ACTION_UP:

                    boolean prepressed = (mPrivateFlags & PFLAG_PREPRESSED) != 0;

                    if ((mPrivateFlags & PFLAG_PRESSED) != 0 || prepressed) {

                        // take focus if we don't have it already and we should in

                        // touch mode.

                        boolean focusTaken = false;

                        if (isFocusable() && isFocusableInTouchMode() && !isFocused()) {

                            focusTaken = requestFocus();

                        }

 

                        if (prepressed) {

                            // The button is being released before we actually

                            // showed it as pressed.  Make it show the pressed

                            // state now (before scheduling the click) to ensure

                            // the user sees it.

                            setPressed(true);

                       }

 

                        if (!mHasPerformedLongPress) {

                            // This is a tap, so remove the longpress check

                            removeLongPressCallback();

 

                            // Only perform take click actions if we were in the pressed state

                            if (!focusTaken) {

                                // Use a Runnable and post this rather than calling

                                // performClick directly. This lets other visual state

                                // of the view update before click actions start.

                                if (mPerformClick == null) {

                                    mPerformClick = new PerformClick();

                                }

                                if (!post(mPerformClick)) {

                                    performClick();

                                }

                            }

                        }

 

                        if (mUnsetPressedState == null) {

                            mUnsetPressedState = new UnsetPressedState();

                        }

 

                        if (prepressed) {

                            postDelayed(mUnsetPressedState,

                                    ViewConfiguration.getPressedStateDuration());

                        } else if (!post(mUnsetPressedState)) {

                            // If the post failed, unpress right now

                            mUnsetPressedState.run();

                        }

                        removeTapCallback();

                    }

                    break;

 

                case MotionEvent.ACTION_DOWN:

                    mHasPerformedLongPress = false;

 

                    if (performButtonActionOnTouchDown(event)) {

                        break;

                    }

 

                    // Walk up the hierarchy to determine if we're inside a scrolling container.

                    boolean isInScrollingContainer = isInScrollingContainer();

 

                    // For views inside a scrolling container, delay the pressed feedback for

                    // a short period in case this is a scroll.

                    if (isInScrollingContainer) {

                        mPrivateFlags |= PFLAG_PREPRESSED;

                        if (mPendingCheckForTap == null) {

                            mPendingCheckForTap = new CheckForTap();

                        }

                        postDelayed(mPendingCheckForTap,

                                   ViewConfiguration.getTapTimeout());

                    } else {

                        // Not inside a scrolling container, so show the feedback right away

                        setPressed(true);

                        checkForLongClick(0);

                    }

                    break;

 

                case MotionEvent.ACTION_CANCEL:

                    setPressed(false);

                    removeTapCallback();

                    removeLongPressCallback();

                    break;

 

                case MotionEvent.ACTION_MOVE:

                    final int x = (int) event.getX();

                    final int y = (int) event.getY();

 

                    // Be lenient about moving outside of buttons

                    if (!pointInView(x, y, mTouchSlop)) {

                        // Outside button

                        removeTapCallback();

                        if ((mPrivateFlags & PFLAG_PRESSED) != 0) {

                            // Remove any future long press/tap checks

                            removeLongPressCallback();

 

                            setPressed(false);

                        }

                    }

                    break;

            }

            return true;

        }

 

        return false;

    }

代码太长,我们只看重点,在ACTION_UP这个case当中,我们找到了关键的代码(第109行):performClick()。

至此,我们已经基本搞清楚了回调机制的整个过程。


    
 
 

您可能感兴趣的文章:

  • Android中回调接口的使用介绍
  • C/C++回调函数介绍
  • linux c 生成随机数srand函数和rand函数介绍及代码示例
  • 请问有没头函数<pthread.h>和<signal.h>里的函数的详细功能介绍?和使用方法???
  • cityhash 32位,64位和128位介绍及函数列表
  • Oracle round()函数与trunc()函数区别介绍
  • Python类的构造函数,析构函数以及垃圾回收机制详细介绍及代码举例
  • Oracle 系统变量函数介绍
  • c++ stl容器set成员函数介绍及set集合插入,遍历等用法举例
  • jquery中map函数与each函数的区别实例介绍
  • php中检测变量是否是一个对象的is_object函数介绍及用法举例
  • 谁有介绍UNIX下面函数的书啊,类似UNIX编程参考手册的东西
  • libpcap工作原理及抓包主要函数介绍
  • 菜鸟级的问题,介绍各种类和函数的文档
  • php session_id()函数介绍及代码实例
  • 哪位大侠,帮忙介绍下prom_getenv 这个函数。谢谢
  • Windows和Linux下C++类成员方法作为线程函数方法介绍
  • 那里有关于JSP的函数、方法、属性的介绍(中文版的)?
  • php中session_id()函数详细介绍,会话id生成过程及session id长度
  • 有没有介绍gcc函数库的书
  • php将html特殊字符转换成html字符串的函数:htmlspecialchars()介绍及代码举例
  • Mysql存储过程和函数区别介绍
  • unix/Linux下c/c++ pthread库读写锁函数介绍
  • SQL的SUBSTR()函数使用介绍
  •  
    本站(WWW.)旨在分享和传播互联网科技相关的资讯和技术,将尽最大努力为读者提供更好的信息聚合和浏览方式。
    本站(WWW.)站内文章除注明原创外,均为转载、整理或搜集自网络。欢迎任何形式的转载,转载请注明出处。












  • 相关文章推荐
  • android 4.0 托管进程介绍及优先级和回收机制
  • 谁能介绍下linux的窗口管理机制,谢谢!
  • 谁能介绍一下linux中寻找lib(so文件)的机制,
  • 请详细介绍一下共享内存机制~~
  • 【一周话题】介绍Linux 2.6.13 内核中新引入的文件系统变化通知机制 inotify
  • python中的五种异常处理机制介绍
  • 基于java中stack与heap的区别,java中的垃圾回收机制的相关介绍
  • PHP中copy on write写时复制机制介绍
  • php中session过期时间设置及session回收机制介绍
  • C#垃圾回收机制的详细介绍
  • Android多线程处理机制中的Handler使用介绍
  • 实例介绍PHP的Reflection反射机制
  • java.applet类applet的类成员方法: getcodebase定义及介绍
  • 我觉得介绍InstallAnyWhere的文档,太少了,请大家介绍一下,英文也可以◎◎◎◎◎◎◎◎
  • java命名空间java.awt接口adjustable的类成员方法: getvisibleamount定义及介绍
  • 请大家介绍几个关于嵌入式Linux开发的站点!最好介绍几个国外的!
  • java命名空间java.awt接口adjustable的类成员方法: getvalue定义及介绍
  • javacc,有研究过的朋友给介绍介绍,谢了
  • java命名空间java.awt类color的类成员方法: orange定义及介绍
  • 那里有关于jmf的开发资料和介绍,请那位仁兄帮忙(最好介绍一些好的资料)急!!
  • java命名空间java.awt类component.bltbufferstrategy的类成员方法: revalidate定义及介绍
  • 小弟对PROC不太了解,但老板要求用它开发,帮帮忙(介绍介绍相关的资源或网站)
  • java命名空间java.awt类component.flipbufferstrategy的类成员方法: destroybuffers定义及介绍
  • 麻烦大家给介绍介绍几本J2EE的入门书呗
  • java命名空间java.awt类cursor的类成员方法: predefined定义及介绍
  • 给我介绍几本学linux的好书,介绍就给分!!!!!
  • java命名空间java.awt类cursor的类成员方法: gettype定义及介绍
  • 急!!谁了解macintosh?能不能给我介绍介绍?是不是跟linux差不多?使用开发工具JDK,这是不是不JAVA?
  • java命名空间java.awt类event的类成员方法: pgdn定义及介绍
  • 怎么没有讨论XML的?哪位高手介绍介绍在JAVA中怎么使用XML?
  • java命名空间java.awt类event的类成员方法: down定义及介绍


  • 站内导航:


    特别声明:169IT网站部分信息来自互联网,如果侵犯您的权利,请及时告知,本站将立即删除!

    ©2012-2021,,E-mail:www_#163.com(请将#改为@)

    浙ICP备11055608号-3