?? ? ? 試想這么一個情景:A需要做某件事,讓B幫忙做,B說我忙完手上的事情就去幫你做。但A總不能在哪干等著吧,因此,A就繼續(xù)去做其他事情,讓B做完之后通知A。
?? ? ? 對于一個這樣的業(yè)務(wù)場景,解決方案有兩種,一種是上文我們介紹的通過Callable和Future來實現(xiàn)。另一種方案就是本文所介紹的回調(diào)機制。
?? ? ? 為了方便理解,我們先說說什么叫調(diào)用?模塊之間存在著一定的接口,供別人調(diào)用。而所謂的回調(diào)就是兩個模塊(對象)相互調(diào)用,包括同步調(diào)用和異步調(diào)用。但回調(diào)絕對不是為了解決調(diào)用時等待時間過長的問題(這是異步的工作),根據(jù)是否等待進一步分為同步和異步?;卣{(diào)函數(shù)的實現(xiàn)一般有三個特點:
?? ? ? ?? ? ? 特點1:類A需要實現(xiàn)我們定義的回調(diào)接口,方便B通知A。
?? ? ? ?? ? ? 特點2:類A需要包含一個類B的引用
?? ? ? ?? ? ? 特點3:類B中有一個參數(shù)為回調(diào)接口的函數(shù)
?? ? ? 下面我們來看下異步回調(diào)的具體實現(xiàn),我們以經(jīng)典的打電話為例,有一天小王遇到一個很難的問題,問題是“1 + 1 = ?”,就打電話問小李,小李一下子也不知道,就跟小王說,等我辦完手上的事情,就去想想答案,小王也不會傻傻的拿著電話去等小李的答案吧,于是小王就對小李說,我還要去逛街,你知道了答案就打我電話告訴我,于是掛了電話,自己辦自己的事情,過了一個小時,小李打了小王的電話,告訴他答案是2。
?? ? ? 首先我們需要定義一個回調(diào)接口,用于B完成A交代的任務(wù)后特告A我做完了。
/**
* 這是一個回調(diào)接口
*
*/
public interface CallBack {
/**
* 這個是小李知道答案時要調(diào)用的函數(shù)告訴小王,也就是回調(diào)函數(shù)
* @param result 是答案
*/
public void solve(String result);
}
?? ? ? 聲明了回調(diào)接口后,對于A,需要滿足兩個回調(diào)機制的特點,首先需要實現(xiàn)我們的回調(diào)接口CallBack,然后再聲明一個B的引用,方便讓B做事情。這里需要小王調(diào)用小李的方法。
/**
* 這個是小王
* 實現(xiàn)了一個回調(diào)接口CallBack,回調(diào)機制特點1
*/
public class Wang implements CallBack {
/**
* 小李對象的引用 相當回調(diào)機制特點2
*/
private Li li;
/**
* 小王的構(gòu)造方法,持有小李的引用
* @param li
*/
public Wang(Li li){
this.li = li;
}
/**
* 小王通過這個方法去問小李的問題
* @param question 就是小王要問的問題,1 + 1 = ?
*/
public void askQuestion(final String question){
//這里用一個線程就是異步,
new Thread(new Runnable() {
@Override
public void run() {
/**
* 小王調(diào)用小李中的方法,在這里注冊回調(diào)接口
* 體現(xiàn)的類A調(diào)用類B
*/
li.executeMessage(Wang.this, question);
}
}).start();
//小網(wǎng)問完問題掛掉電話就去干其他的事情
play();
}
public void play(){
System.out.println("我去忙了");
}
/**
* 小李知道答案后調(diào)用此方法告訴小王,就是所謂的小王的回調(diào)方法
*小李調(diào)用小王的這個方法
*/
@Override
public void solve(String result) {
System.out.println("小李告訴小王的答案是--->" + result);
}
}
?? ? ? 接下來是小李,同樣,小李也需要調(diào)用小王的方法這樣雙向才能滿足回調(diào)。
/**
* 這個就是小李啦
*
*/
public class Li {
/**
* 相當于B類有參數(shù)為CallBack callBack的f(),回調(diào)機制特點3
* @param callBack
* @param question 小王問的問題
*/
public void executeMessage(CallBack callBack, String question){
System.out.println("小王問的問題--->" + question);
//模擬小李辦自己的事情需要很長時間
for(int i=0; i<10000;i++){
}
/**
* 小李辦完自己的事情之后想到了答案是2
*/
String result = "答案是2";
/**
* 于是就打電話告訴小王,調(diào)用小王中的方法
* 這就相當于B類反過來調(diào)用A的方法
*/
callBack.solve(result);
}
}
?? ? ? 回調(diào)函數(shù)的實現(xiàn)是一個相互調(diào)用的過程,只要牢記我們提到的回調(diào)函數(shù)的三個特點,就能很容易的寫出函調(diào)程序。