所谓回调,就是客户程序C调用服务程序S中的某个函数A,然后S又在某个时候反过来调用C中的某个函数B,对于C来说,这个B便叫做回调函数。例如Win32下的窗口过程函数就是一个典型的回调函数。一般说来,C不会自己调用B,C提供B的目的就是让S来调用它,而且是C不得不提供。由于S并不知道C提供的B姓甚名谁,所以S会约定B的接口规范(函数原型),然后由C提前通过S的一个函数R告诉S自己将要使用B函数,这个过程称为回调函数的注册,R称为注册函数。Web Service以及Java的RMI都用到回调机制,可以访问远程服务器程序。重新举个例子来理解回调:
我遇到了一个问题,便用家里的固话打给我的同事,他说不太清楚,稍后给我回复。我说我一会要出去,你想到了之后打我手机吧。没过多久,我同事就打手机过来告诉了我答案。
下面是代码:
1.先定义一个接口,规定回答问题的条件是打我手机
public interface CallBack { //通过手机回答 void CallIphone(); }
2.调用者(我):
public class Me { public void askQuestion(){ System.out.println("拨打固话问1+1=?"); } }
3.被调用者(同事):
public class You { public void answer(CallBack callBack){ //进行回调 callBack.CallIphone(); } public static void main(String[] args) throws InterruptedException { new Me().askQuestion(); Thread.sleep(3000); new You().answer(new CallBack() { //实现接口,即回答问题的方式 public void CallIphone() { System.out.println("拨打手机回答等于2"); } }); } }
4.显示结果
拨打固话问1+1=?
拨打手机回答等于2
*********************************************************************************************************************************************************************************
* Created by IntelliJ IDEA.
* User: leizhimin
* Date: 2008-7-31 13:18:33
* 事件接口
*/
public interface Event {
/**
* 返回发生事件信息
*
* @return 事件信息
*/
public String happendEvent();
}
* Created by IntelliJ IDEA.
* User: leizhimin
* Date: 2008-7-31 13:18:14
* 事件A
*/
public class EventA implements Event {
/**
* 返回发生事件信息
*
* @return 事件信息
*/
public String happendEvent() {
return "发生了事件 EventA!";
}
}
* Created by IntelliJ IDEA.
* User: leizhimin
* Date: 2008-7-31 13:18:21
* 事件B
*/
public class EventB implements Event{
/**
* 返回发生事件信息
* @return 事件信息
*/
public String happendEvent() {
return "发生了事件 EventB!";
}
}
* Created by IntelliJ IDEA.
* User: leizhimin
* Date: 2008-7-31 13:20:48
* 工人
*/
public class Worker {
private Event event; //事件
private String name; //工人姓名
private Boss boss; //工人所属的老板
public Worker(String name, Boss boss) {
this.name = name;
this.boss = boss;
}
/**
* 干活
*/
public void doWork() {
System.out.println(name + " is doing working...");
//工人挺辛苦,干着枯燥乏味的重复工作,哈哈
for ( int i = 0; i < 2000000; i++) {
int x = i / 234 + 234;
}
System.out.println(name + " was finished work.");
//向老板说明发生的情况
boss.getWorkerEvent( this, event);
}
public Event getEvent() {
return event;
}
public void setEvent(Event event) {
this.event = event;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
* Created by IntelliJ IDEA.
* User: leizhimin
* Date: 2008-7-31 13:26:22
* 老板
*/
public class Boss {
private String name;
public Boss(String name) {
this.name = name;
}
/**
* 老板接收工人的事件
* @param worker 工人
* @param event 事件
*/
public void getWorkerEvent(Worker worker, Event event) {
System.out.println( "老板接收到事件信息: "+worker.getName() + ": " + event.happendEvent());
}
}
* Created by IntelliJ IDEA.
* User: leizhimin
* Date: 2008-7-31 13:35:38
* 测试类
*/
public class Test {
public static void main(String args[]){
//初始化老板和工人
Boss boss = new Boss( "老板");
Worker worker1= new Worker( "张三",boss);
Worker worker2= new Worker( "李四",boss);
//捏造两个事件
Event event1 = new EventA();
Event event2 = new EventB();
//事件是工人发出的
worker1.setEvent(event1);
worker2.setEvent(event2);
//工人干活,干完了通知老板干的情况如何
worker1.doWork();
worker2.doWork();
}
}
张三 was finished work.
老板接收到事件信息: 张三: 发生了事件 EventA!
李四 is doing working...
李四 was finished work.
老板接收到事件信息: 李四: 发生了事件 EventB!
Process finished with exit code 0
*********************************************************************************************************************************************************************************
下面使用java回调函数来实现一个测试函数运行时间的工具类:
如果我们要测试一个类的方法的执行时间,通常我们会这样做:
- public class TestObject {
- /**
- * 一个用来被测试的方法,进行了一个比较耗时的循环
- */
- public static void testMethod(){
- for(int i=0; i<100000000; i++){
- }
- }
- /**
- * 一个简单的测试方法执行时间的方法
- */
- public void testTime(){
- long begin = System.currentTimeMillis();//测试起始时间
- testMethod();//测试方法
- long end = System.currentTimeMillis();//测试结束时间
- System.out.println("[use time]:" + (end - begin));//打印使用时间
- }
- public static void main(String[] args) {
- TestObject test=new TestObject();
- test.testTime();
- }
- }
大家看到了testTime()方法,就只有"//测试方法"是需要改变的,下面我们来做一个函数实现相同功能但更灵活:
首先定一个回调接口:
- public interface CallBack {
- //执行回调操作的方法
- void execute();
- }
然后再写一个工具类:
- public class Tools {
- /**
- * 测试函数使用时间,通过定义CallBack接口的execute方法
- * @param callBack
- */
- public void testTime(CallBack callBack) {
- long begin = System.currentTimeMillis();//测试起始时间
- callBack.execute();///进行回调操作
- long end = System.currentTimeMillis();//测试结束时间
- System.out.println("[use time]:" + (end - begin));//打印使用时间
- }
- public static void main(String[] args) {
- Tools tool = new Tools();
- tool.testTime(new CallBack(){
- //定义execute方法
- public void execute(){
- //这里可以加放一个或多个要测试运行时间的方法
- TestObject.testMethod();
- }
- });
- }
- }
大家看到,testTime()传入定义callback接口的execute()方法就可以实现回调功能
*********************************************************************************************************************************************************************************
回调方法是把功能定义和功能实现分离的一种手段,是一种松耦合的设计思想。
Android中的控件响应就是利用了回调方法。话不多说,直接上代码。
回调方法的接口:
- public interface ICallBack {
- // 回调方法
- public void callBackMethod();
- }
回调方法的实现类(监听类):
- /**
- * 监听类
- * @author zuolongsnail
- */
- public class CallBackListener implements ICallBack {
- @Override
- public void callBackMethod() {
- System.out.println("回调");
- }
- }
回调方法的调用类:
- /**
- * 调用类
- * @author zuolongsnail
- */
- public class Caller {
- private CallBackListener callBack;
- public void setCallBack(CallBackListener callBack){
- this.callBack = callBack;
- }
- public void call(){
- this.callBack.callBackMethod();
- }
- }
业务处理类:
- /**
- * 业务处理类
- * @author zuolongsnail
- */
- public class Main {
- public static void main(String[] args) {
- Caller caller = new Caller();
- caller.setCallBack(new CallBackListener());
- // 在业务处理的时候调用
- caller.call();
- }
- }
熟悉Android中Button点击事件处理的同学应该都知道跟上面是一样的。
ICallBack------->OnClickListener接口
CallBackListener--------->实现OnClickListener接口的类
Caller-------->Button对象
Main-------->业务处理类(Activity)