同步回调
类A中方法a调用了类B的方法b,方法a等待方法b执行完才能继续执行。
举个例子:
某天,小A在用计算机执行某些任务,但有个任务小A不会。
于是小A叫来小B帮忙。
由于计算机只有一台,所以小A让小B先帮忙实现那个自己不会的任务。
小B很快的完成了这个任务。
然后小A也很快的完成了剩下的任务。
异步回调
类A中方法a调用了类B中的方法b,给方法b单独开启一个线程,方法a和方法b同时执行,方法b完成后调用回调方法通知方法a。
举个例子:
又一天,小A用计算机执行某些任务,小A又碰到了一个不会的任务。
于是小A又叫来小B帮忙。
不过,这次小A多准备了一台计算机,一共有两台计算机。
小A继续执行剩下的任务,同时小B帮助小A实现那个小A不会的任务。
小B完成任务后通知小A。
下面通过一个网络下载的例子举例说明异步回调。
public class httpUtils {
public static String get(){
new Thread(new Runnable() {
public void run() {
for(int i = 0; i < 10; ++i){
System.out.println("数据已经下载"+i*10+"%");
try {
Thread.sleep(500);
} catch (InterruptedException e) {
// TODO: handle exception
}
}
}
}).start();
try {
Thread.sleep(2000);
} catch (Exception e) {
// TODO: handle exception
}
return "下载完成";
}
}
首先在httpUtils类中有个get方法。get里面启动了一个线程用来下载数据,当数据下载完成后,返回“下载完成”的字符串。
String str = httpUtils.get();
System.out.println(str);
调用get方法并打印结果。
数据已经下载0%
数据已经下载10%
数据已经下载20%
数据已经下载30%
下载完成
数据已经下载40%
数据已经下载50%
数据已经下载60%
数据已经下载70%
数据已经下载80%
数据已经下载90%
我们并没有下载完所有的数据,它就提示我们下载完成了。
这肯定是有问题的。我们分析一下上述代码。
首先我们在主线程中调用了httpUtils的get方法。在get方法中我们做了这样一件事情。
我们又启动了一个线程用来下载数据。但我们不知道数据什么时候能下载完成,于是启动一个定时器进行等待。
当数据下载的时候,get方法继续执行,进入定时器等待。
但很明显定时器超时,任务还没完成。但这时候get方法仍然只能通知我们任务完成了。
由此分析,我们可以清晰的发现问题----我们并不知道什么时候数据下载完成。
再看下面的代码。
public class httpUtils2 {
interface MyHttpListener{
public void handleData(String str);
public void handleError(String str);
}
public static void setMyHttpListener(MyHttpListener myHttpListener){
get(myHttpListener);
}
public static void get(MyHttpListener myHttpListener){
new Thread(new Runnable() {
public void run() {
for(int i = 0; i < 10; ++i){
System.out.println("数据已经下载"+i*10+"%");
try {
Thread.sleep(500);
} catch (InterruptedException e) {
// TODO: handle exception
}
}
myHttpListener.handleData("下载完成");
}
}).start();
}
}
httpUtils2.setMyHttpListener(new httpUtils2.MyHttpListener(){
public void handleData(String str){
System.out.println(str);
}
public void handleError(String str){
}
});
结果如下。
数据已经下载0%
数据已经下载10%
数据已经下载20%
数据已经下载30%
数据已经下载40%
数据已经下载50%
数据已经下载60%
数据已经下载70%
数据已经下载80%
数据已经下载90%
下载完成
结果符合预期效果,我们继续分析。
在这里首先httpUtils2调用了setMyHttpListener方法。setMyHttpListener方法中又调用了get方法。
同样在get方法中我们启动了一个线程来下载数据。
注意这里在数据下载完成后,我们将“下载完成”传入了接口MyHttpListener的handleData方法中。
我们在httpUtils2类中只申明了MyHttpListener接口。
我们将“实例化”的MyHttpListener接口传入了setMyHttpListener方法中(注意这里是匿名类的形式)。
在这里我们知道数据是什么时候下载完成的吗?我们还是不知道。
但我们不用管,我们只需要知道当数据下载完成后就会调用handleData方法,并传入相关数据。
而handleData的实现是由我们自己决定的。