类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的实现是由我们自己决定的。
