内容简介:
- 接口回调的理解及需要关注的问题
- 接口回调一般常规用法
- 接口回调简洁用法
- 接口回调的意义
接口回调简介:
简单的说接口回调就是:调用者A类访问了被调用者B类中的M方法.这个M方法在执行完毕后又调用了A类中的方法.
问题?
B类中的M方法是如何访问A类中的方法的呢?弄清了这个问题,也就明白了接口回调.
下面我们根据一个场景描述去编写代码:
我们在调用者Caller类中使用被调用者Collee类中的下载文件方法DownLoadFile().下载完成后要通知Caller类文件加载完成.这个时候Caller类才能去访问刚才下载的资源.由于下载需要时间.而Caller类还有其他事情要做.不能等着下载完成后再去做.这样的话下载的方法必须开启新的线程去下载.
接口回调一般常规用法
代码实现:1.接口和回调方法:
/*
CallBackListener (回调监听接口)
用于回调的接口 (接口内的抽象方法用于监听被调用者返回的结果)
接口中有回调方:该回调方法是被调用者通过回调接口对象去访问调用者的方法.所以形参应该是被调用者返回给调用者结果的数据类型和参数个数。
*/
public interface CallBackListener {
//发送消息给调用者
public abstract void sendMessage2Caller(String msg);
}
2.调用者类:
/*
Caller :(调用者)
调用者在访问被调用者的方法前.必须将回调接口对象设置给被调用者.以方便被调用者使用接口回调对象访问自己.
*/
public class Caller {
public static void main(String[] args) {
//1.创建被调用者对象
Callee callee = new Callee();
//2.创建回调接口对象.
CallBackListener cb = new CallBackListener() {
@Override
public void sendMessage2Caller(String msg) {
//打印回调传递过来的结果
System.out.println(msg);
}
};
//3.必须将回调接口对象设置给被调用者
callee.setCallBackListener(cb);
//4.访问被调用者的下载文件方法.这个方法完成后被调用者会通过回调接口对象通知我们.
callee.DownLoadFile();
System.out.println("你下载真慢,我先去忙别的事了....");
}
}
3.被调用者类
/*
Callee(被调用者):
1.被调用者类中必须有回调接口类型的变量.
2.并且还要有给该变量赋值的setXxx()方法.
3.在可以给调用者返回结果的时候.拿着接口类型的变量调用接口的方法进行对调用者的访问.(因为接口类型的变量要执行的方法在调用者那里存在).
*/
public class Callee {
//1.被调用者类中必须有 回调接口类型的变量.
private CallBackListener cb;
//2.并且还要有给该变量赋值的setXxx()方法.
public void setCallBackListener(CallBackListener cb){
this.cb = cb;
}
/**
* 下载文件是非常耗时的工作.而调用者又需要在下载完成后读取下载的文件.
* 所以当这个方法完成下载后应该立刻通知调用者.这个通知的动作就称之为回调.
* @throws InterruptedException
*/
public void DownLoadFile(){
//开启新的线程去下载.异步任务.
new Thread(){
public void run() {
long start = System.currentTimeMillis();
//使用睡眠模拟耗时工作.
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
long end = System.currentTimeMillis();
//完成下载后通知调用者
if(cb != null){
cb.sendMessage2Caller("下载完成,耗时:"+(end-start)/1000+"秒,你可以去访问资源了.");
}
};
}.start();
}
}
运行结果如下:
5秒钟后
接口回调简洁用法
代码实现:
1.接口和回调方法:
/*
CallBackListener (回调监听接口)
用于回调的接口 (接口内的抽象方法用于监听被调用者返回的结果)
接口中有回调方:该回调方法是被调用者通过回调接口对象去访问调用者的方法.所以形参应该是被调用者返回给调用者结果的数据类型和参数个数。
*/
public interface CallBackListener {
//发送消息给调用者
public abstract void sendMessage2Caller(String msg);
}
2.调用者类:
public class Caller {
public static void main(String[] args) {
//1.创建被调用者对象
Callee callee = new Callee();
//2.访问被调用者的下载文件方法.这个方法完成后被调用者会通过回调接口对象通知我们.
//使用匿名内部类对象当做参数传递.更加简洁
callee.DownLoadFile(new CallBackListener() {
@Override
public void sendMessage2Caller(String msg) {
//打印回调传递过来的结果
System.out.println(msg);
}
});
System.out.println("你下载真慢,我先去忙别的事了....");
}
}
3.被调用者类
/**
* 下载文件是非常耗时的工作.而调用者又需要在下载完成后读取下载的文件.
* 所以当这个方法完成下载后应该立刻通知调用者.这个通知的动作就称之为回调.
* final CallBackListener cb 匿名内部类访问局部变量必须加final.
*/
public class Callee {
public void DownLoadFile(final CallBackListener cb){
//开启新的线程去下载.异步任务.
new Thread(){
public void run() {
long start = System.currentTimeMillis();
//使用睡眠模拟耗时工作.
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
long end = System.currentTimeMillis();
//完成下载后通知调用者
if(cb != null){
cb.sendMessage2Caller("下载完成,耗时:"+(end-start)/1000+"秒,你可以去访问资源了.");
}
};
}.start();
}
}
接口回调的意义:
通过以上两个案例大家会不会有一个疑问.为什么要搞一个接口呢?把接口换成普通的类可以吗?当然是可以的.这里之所以使用接口回调.是因为接口具有规范性和灵活性.特别是规范性.
代码举例:
1.原来的接口换成抽象类其他两个类不变, 不会影响运行效果
public abstract class CallBackListener {
//发送消息给调用者
public abstract void sendMessage2Caller(String msg);
}
2.原来的接口换成类其他两个类不变, 不会影响运行效果public class CallBackListener {
//发送消息给调用者
public void sendMessage2Caller(String msg){
};
}