-
接口回调的理解及需要关注的问题
-
接口回调一般常规用法
-
接口回调简洁用法
-
接口回调的意义
接口回调简介:
简单的说接口回调就是:调用者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() { 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() { 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){
};
}