call back function

来源:互联网 发布:淘宝微淘推广软件 编辑:程序博客网 时间:2024/05/02 02:49

用一个比较形象的例子:

你饿了,想吃饭,就一会去问你妈一声"开饭没有啊?"

这就是正常函数调用.
但是今天你妈包饺子,花的时间比较长,你跑啊跑啊,就烦了.于是你给你妈说,我先出去玩会,开饭的时候打我手机.

等过了一阵,你妈给你打电话说"开饭啦,回来吃饭吧!"
其中,你告诉你妈打手机找你,就是你把回调函数句柄保存到你妈的动作.你妈打电话叫你,就是个回调过程.

下面用一个Android中应用到"回调"的场景,来进一步解释。

[java] view plain copy print?在CODE上查看代码片派生到我的代码片
  1. Button button = (Button)this.findViewById(R.id.button);  
  2. button.setOnClickListener(new Button.OnClickListener() {  
  3.   
  4.   //回调函数  
  5.   @override  
  6.   publicvoid onClick(View v) {  
  7.     buttonTextView.setText("按钮被点击了");  
  8.   }  
  9. });  

这里肯定很熟悉了,给Button设置监听器

这其实就是"回调"最常见的应用场景之一。我们自己不会显示地去调用onClick方法。用户触发了该按钮的点击事件后,它会由Android系统来自动调用。

 

在这里我们用代码,模拟注册事件监听器。
先写一个监听器接口

[java] view plain copy print?在CODE上查看代码片派生到我的代码片
  1. package com.listener;  
  2.   
  3. /** 
  4.  * 点击监听器接口 
  5.  * @author jason0539 
  6.  * 
  7.  */  
  8. public interface MyOnClickListener {  
  9.     public void onClick();  
  10. }  

然后写一个我们自己的Button类

[java] view plain copy print?在CODE上查看代码片派生到我的代码片
  1. package com.listener;  
  2.   
  3. public class MyButton {  
  4.     private MyOnClickListener listener;  
  5.       
  6.     /** 
  7.      * 设置具体点击监听器 
  8.      * @param listener 点击监听器实现类 
  9.      */  
  10.     public void setOnClickListener(MyOnClickListener listener) {  
  11.         this.listener = listener;  
  12.     }  
  13.       
  14.     /** 
  15.      * 按钮被点击 
  16.      */  
  17.     public void doClick() {  
  18.         listener.onClick();  
  19.     }  
  20. }  

最后模拟Client端的注册监听器和触发点击操作。

[java] view plain copy print?在CODE上查看代码片派生到我的代码片
  1. package com.listener;  
  2.   
  3. publicclass Client {  
  4.     public static void main(String[] args) {  
  5.         MyButton button =new MyButton();  
  6.         //注册监听器  
  7.         button.setOnClickListener(new MyOnClickListener() {  
  8.   
  9.             @Override  
  10.             public void onClick() {  
  11.                 System.out.println("按钮被点击了");  
  12.                   
  13.             }  
  14.               
  15.         });  
  16.         //模拟用户点击  
  17.         button.doClick();  
  18.     }  
  19. }  

以上就是"回调"思想在Java中事件监听的运用

用心体会一下,是不是就知道,什么是CallBack,什么是回调函数了.

作者:jason0539

微博:http://weibo.com/2553717707

博客:http://blog.csdn.net/jason0539(转载请说明出处)


1.回调函数与普通函数的区别
从概念上讲,回调函数与普通函数的本质在于:调用者的不同。普通函数由程序员代码调用,而回调函数由操作系统在适当的时间调用。   
回调函数主要用于处各种事件和处理。由于WINDOWS系统中存在大量程序员事先不可知的事件,例如鼠标的单击,程序员事先无法得知终端用户何时会发出此动作,因此只能:  
  A。定义事件的处理逻辑,与普通函数的 编程 一样;  
  B。告之操作系统自己的处理逻辑,即通知操作系统函数指针;VC/VB等现代编程语言通过事件编程机制隐藏了这一步;  
  C。操作系统在事件出现时,调用指定的函数(回调函数的概念)处理,这一步完全由系统负责。   
回调函数在各种操作系统中普遍存在,是现代操作系统为程序员提供处理异步事件的基本机制之一,在不同的系统中的具体实现方式各不相同;请参阅随机文档。Callback 函数实质就是你实现这个函数,由操作系统调用。而一般的情况下是,操作系统提供函数由你来调用的。

2.回调函数实际上就起到了消息循环的作用,因为在sdk中只有通过回调函数来发送各自的处理消息

3.C/C++实现
象C/C++这样支持函数指针的语言都有回调函数的概念,它实际上是向被调用函数传一个你的函数地址,然后被调用函数向通过你传入的函数地址来调用你的函数。比如你做了一个遍历树的函数,但你不知遍历者将对各节点做何种处理时,你就可以在这个遍历函数中加一个函数地址的参数,这样调用者在遍历该树时就可以做各种有意义的工作了:比如打印各节点数据、汇总所有节点之类。

4.Windows
回调函回调函数是用来处理窗口消息的函数,一般类型为  
   WindowProc(HWND    hWnd,UINT    message,    WPARAM    wParam,    LPARAM    lParam);  
   hWnd为窗口句柄,message为消息ID,后面两个为消息参数。
MFC将一部分处理消息的函数封状在CWnd类中,如OnCreate等,其参数也从WPARAM    wParam,    LPARAM   lParam转换为LPCREATESTRUCT 结构 (可以查看映射宏定义及MFC源代码)而其他的有些也可以用回调函数,如WM_TIMER消息,可以在SetTimer函数里面第三个参数指定回调函数,若为NULL则应该在OnTimer函数中处理改消息。

5.MSDN中的描述
               Used    to    asynchronously    read    the    messages    in    a    queue.    It    is    an   application-defined    function   that    MSMQ    calls    when    a    message    is    available,    a   time-out    occurs,    or    an    error    occurs.   

6.Callback最本质的特征包括两点:注册和触发
Callback函数是你提供给系统调用的函数。很多情况下,系统某个情况下,定义需要执行某个操作,而操作本身由
有用户的程序来提供,这时,就要用到回调函数了。所以,简单地说。回调函数,就是你写一个函数,在系统定义的
地点提供给系统调用。
举个例子:SetTimer(),一种处理是,你响应WM_TIMER消息,这暂且不讨论;还有一种用法,就是你提供一个函
数,让系统在产生timer消息时自动调用,这种情况下,你可以写好一个timer消息的处理函数,把函数的地址作为
SetTimer()的参数,而你这个timer消息的处理函数,就是回调函数。
==================================
回调函数的作用   原文地址: http://wmnmtm.blog.163.com/blog/static/3824571420105484116877/
一直不太理解回调函数的作用,下面是找到的一些关于回调函数的作用的解答。

1.回调函数是一个很有用,也很重要的概念。当发生某种事件时,系统或其他函数将会自动调用你定义的一段函数。

2.回调函数就相当于一个中断处理函数,由系统在符合你设定的条件时自动调用。为此,你需要做三件事:1,声明;2,定义;3,设置触发条件,就是在你的函数中把你的回调函数名称转化为地址作为一个参数,以便于系统调用。

3.所谓回调函数就是按照一定的形式由你定义并编写实现内容,当发生某种事件时,而由系统或其它函数来调用的函数。使用回调函数实际上就是在调用某个函数时,将自己编写的一个函数的地址作为参数传递给那个函数。而那个函数在需要的时候,也就是某种事情发生的时候,利用传递的函数地址调用回调函数,这时你可以利用这个机会在回调函数中处理消息或完成一定的操作。回调函数只能是全局函数,或者是静态函数,因为这个函数只是在这个类中使用,所以为了维护类的完整性,我们用类的静态成员函数来做回调函数。

4.对于很多初学者来说,往往觉得回调函数很神秘,很想知道回调函数的工作原理。本文将要解释什么是回调函数、它们有什么好处、为什么要使用它们等等问题,在开始之前,假设你已经熟知了函数指针。

(1)什么是回调函数?
  
简而言之,回调函数就是一个通过函数指针调用的函数。如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用为调用它所指向的函数时,我们就说这是回调函数。

(2)为什么要使用回调函数?
  
因为可以把调用者与被调用者分开。调用者不关心谁是被调用者,所有它需知道的,只是存在一个具有某种特定原型、某些限制条件(如返回值为int)的被调用函数。
  
如果想知道回调函数在实际中有什么作用,先假设有这样一种情况,我们要编写一个库,它提供了某些排序算法的实现,如冒泡排序、快速排序、shell排序、shake排序等等,但为使库更加通用,不想在函数中嵌入排序逻辑,而让使用者来实现相应的逻辑;或者,想让库可用于多种数据类型(int、float、string),此时,该怎么办呢?可以使用函数指针,并进行回调。
  
回调可用于通知机制,例如,有时要在程序中设置一个计时器,每到一定时间,程序会得到相应的通知,但通知机制的实现者对我们的程序一无所知。而此时,就需有一个特定原型的函数指针,用这个指针来进行回调,来通知我们的程序事件已经发生。实际上,SetTimer()API使用了一个回调函数来通知计时器,而且,万一没有提供回调函数,它还会把一个消息发往程序的消息队列。
  
另一个使用回调机制的API函数是EnumWindow(),它枚举屏幕上所有的顶层窗口,为每个窗口调用一个程序提供的函数,并传递窗口的处理程序。如果被调用者返回一个值,就继续进行迭代,否则,退出。EnumWindow()并不关心被调用者在何处,也不关心被调用者用它传递的处理程序做了什么,它只关心返回值,因为基于返回值,它将继续执行或退出。
  
不管怎么说,回调函数是继续自C语言的,因而,在C++中,应只在与C代码建立接口,或与已有的回调接口打交道时,才使用回调函数。除了上述情况,在C++中应使用虚拟方法或函数符(functor),而不是回调函数。
================

0 0
原创粉丝点击