android 等待回调再返回结果_震惊!!只剩你还不懂Java回调机制了!
點(diǎn)擊上方?Java項(xiàng)目學(xué)習(xí)?,選擇?星標(biāo)?公眾號(hào)
重磅資訊、干貨,第一時(shí)間送達(dá)? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?來(lái)源:22j.co/cFPf
調(diào)用和回調(diào)機(jī)制
在一個(gè)應(yīng)用系統(tǒng)中, 無(wú)論使用何種語(yǔ)言開(kāi)發(fā), 必然存在模塊之間的調(diào)用, 調(diào)用的方式分為幾種:
1. 同步調(diào)用
同步調(diào)用是最基本并且最簡(jiǎn)單的一種調(diào)用方式, 類(lèi) A 的方法 a() 調(diào)用類(lèi) B 的方法 b(), 一直等待 b() 方法執(zhí)行完畢, a() 方法繼續(xù)往下走. 這種調(diào)用方式適用于方法 b() 執(zhí)行時(shí)間不長(zhǎng)的情況, 因?yàn)?b() 方法執(zhí)行時(shí)間一長(zhǎng)或者直接阻塞的話, a() 方法的余下代碼是無(wú)法執(zhí)行下去的, 這樣會(huì)造成整個(gè)流程的阻塞.
2. 異步調(diào)用
異步調(diào)用是為了解決同步調(diào)用可能出現(xiàn)阻塞, 導(dǎo)致整個(gè)流程卡住而產(chǎn)生的一種調(diào)用方式. 類(lèi) A 的方法方法 a() 通過(guò)新起線程的方式調(diào)用類(lèi) B 的方法 b(), 代碼接著直接往下執(zhí)行, 這樣無(wú)論方法 b() 執(zhí)行時(shí)間多久, 都不會(huì)阻塞住方法 a() 的執(zhí)行.
但是這種方式, 由于方法 a() 不等待方法 b() 的執(zhí)行完成, 在方法 a() 需要方法 b() 執(zhí)行結(jié)果的情況下(視具體業(yè)務(wù)而定, 有些業(yè)務(wù)比如啟異步線程發(fā)個(gè)微信通知、刷新一個(gè)緩存這種就沒(méi)必要), 必須通過(guò)一定的方式對(duì)方法 b() 的執(zhí)行結(jié)果進(jìn)行監(jiān)聽(tīng).
在 Java 中, 可以使用 Future+Callable 的方式做到這一點(diǎn), 具體做法可以參見(jiàn)文章:
http://www.cnblogs.com/xrq730/p/4872722.html
3. 回調(diào)
如下圖所示, 回調(diào)是一種雙向的調(diào)用方式, 其實(shí)而言, 回調(diào)也有同步和異步之分, 講解中是同步回調(diào), 第二個(gè)例子使用的是異步回調(diào)
回調(diào)的思想是:
類(lèi) A 的 a() 方法調(diào)用類(lèi) B 的 b() 方法
類(lèi) B 的 b() 方法執(zhí)行完畢主動(dòng)調(diào)用類(lèi) A 的 callback() 方法
通俗而言: 就是 A 類(lèi)中調(diào)用 B 類(lèi)中的某個(gè)方法 C, 然后 B 類(lèi)中反過(guò)來(lái)調(diào)用 A 類(lèi)中的方法 D, D 這個(gè)方法就叫回調(diào)方法, 這樣子說(shuō)你是不是有點(diǎn)暈暈的, 其實(shí)我剛開(kāi)始也是這樣不理解, 看了人家說(shuō)比較經(jīng)典的回調(diào)方式:
class A 實(shí)現(xiàn)接口 CallBack callback——背景 1
class A 中包含一個(gè) class B 的引用 b ——背景 2
class B 有一個(gè)參數(shù)為 callback 的方法 f(CallBack callback) ——背景 3
A 的對(duì)象 a 調(diào)用 B 的方法 f(CallBack callback) ——A 類(lèi)調(diào)用 B 類(lèi)的某個(gè)方法 C
然后 b 就可以在 f(CallBack callback) 方法中調(diào)用 A 的方法 ——B 類(lèi)調(diào)用 A 類(lèi)的某個(gè)方法 D
回調(diào)的種類(lèi)
回調(diào)分為同步回調(diào)和異步回調(diào), 假如以買(mǎi)彩票的場(chǎng)景來(lái)模擬, 我買(mǎi)彩票, 調(diào)用彩票網(wǎng), 給我返回的結(jié)果確定是否中獎(jiǎng), 同步回調(diào)就是, 我買(mǎi)了彩票之后, 需要等待彩票網(wǎng)給我返回的結(jié)果, 這個(gè)時(shí)候我不能做其他事情, 我必須等待這個(gè)結(jié)果, 這就叫同步回調(diào), 同步, 就意味著等待, 我不能去做其他事情, 必須等待。
異步回調(diào)就是, 我買(mǎi)了彩票之后, 可以去做其他事情, 然后當(dāng)彩票網(wǎng)有了結(jié)果和消息, 再給我返回消息, 其中最明顯的方式就是在得到彩票結(jié)果的函數(shù)之中, 添加一個(gè)其他的方法, 如果我的其他方法可以立即執(zhí)行, 那么就是異步的 (給出是否中獎(jiǎng)需要花費(fèi)很長(zhǎng)的時(shí)間), 而在測(cè)試函數(shù)之中, 前后兩個(gè), 那是發(fā)生在測(cè)試函數(shù)的線程之中的, 肯定是一前一后按照次序的, 在這個(gè)地方不是顯示同步異步的地點(diǎn).
同步回調(diào)
同步回調(diào)和異步回調(diào), 主要體現(xiàn)在其是否需要等待. 同步調(diào)用, 如果被調(diào)用一方的 APi(第三方 API), 處理問(wèn)題需要花很長(zhǎng)時(shí)間, 我們需要等待, 那就是同步回調(diào), 如果調(diào)用完之后不需要理解得到結(jié)果, 我們調(diào)完就走, 去做其他事情, 那就是異步調(diào)用, 異步調(diào)用需要在我們調(diào)用第三方 API 處, 開(kāi)啟一個(gè)新的線程即可, 而同步調(diào)用和平常的調(diào)用沒(méi)有任何區(qū)別.
例子
OrderResult 接口, 其中的方法 getOrderResult
public?interface?OrderResult?{????/**
?????*?訂購(gòu)貨物的狀態(tài)
?????*
?????*?@param?state
?????*?@return
?????*/
????//參數(shù)可以不用,?用不用按照自己的實(shí)際需求決定
????public?String?getOrderResult(String?state);
}
Store 類(lèi), 商店提供會(huì)無(wú)預(yù)定消息返回的接口, 回調(diào) OrderResult 接口的方法, 給其返回預(yù)訂商品的狀態(tài), 重點(diǎn)是 returnOrderGoodsInfo(OrderResult order) 方法, 體現(xiàn)了回調(diào)的回. Store 是被調(diào)用的一方, 被調(diào)用的一方, 要回過(guò)去調(diào)用調(diào)用一方的方法, 這個(gè)方法實(shí)際上是回調(diào)接口的方法.
public?class?Store?{????@Getter
????@Setter
????private?String?name;
????Store(String?name)?{
????????this.name?=?name;
????}
????/*回調(diào)函數(shù),?將結(jié)構(gòu)傳給那個(gè)我們不能直接調(diào)用的方法,?然后獲取結(jié)果*/
????public?String?returnOrderGoodsInfo(OrderResult?order)?{
????????String[]?s?=?{"訂購(gòu)中...",?"訂購(gòu)失敗",?"即將發(fā)貨!",?"運(yùn)輸途中...",?"已在投遞"};
????????Random?random?=?new?Random();
????????int?temp?=?random.nextInt(5);
????????String?s1?=?s[temp];
????????return?order.getOrderResult(s1);
????}
}
SyncBuyer 類(lèi), 同步顧客類(lèi), 其中獲取商品的訂購(gòu)狀態(tài), orderGoods(), 調(diào)用了 store 返回商品調(diào)用信息的 returnOrderGoodsInfo() 方法, 但是在 Store 類(lèi)的 returnOrderGoodsInfo() 方法之中, 以 OrderResult 接口為參數(shù), 反過(guò)來(lái)調(diào)用了 OrderResult 接口, 相當(dāng)于調(diào)用了其子類(lèi) SyncBuyer 本身, 以他為參數(shù), 調(diào)用了 getOrderResult(String state) 方法, 也就是 OrderResult 接口的方法, 相當(dāng)于就完成了一個(gè)調(diào)用的循環(huán), 然后取到了我們自己無(wú)法給出的結(jié)果.
這個(gè)地方的 "循環(huán)", 是回調(diào)的關(guān)鍵所在, 需要正常調(diào)用其他外接提供方法來(lái)獲取結(jié)果的一方, 繼承一個(gè)回調(diào)接口, 實(shí)現(xiàn)它, 然后調(diào)用第三方的 API 方法, 第三方在我們調(diào)用的方法之中, 以回調(diào)結(jié)構(gòu)為參數(shù), 然后調(diào)用了接口中的方法, 其中可以返回相應(yīng)的結(jié)果給我們.
需要說(shuō)明的是, 我們雖然實(shí)現(xiàn)了這個(gè)接口的方法, 但是我們自己的類(lèi)之中, 或者說(shuō)此類(lèi)本身, 卻沒(méi)法調(diào)用這個(gè)方法, 也可以說(shuō), 此類(lèi)調(diào)用這個(gè)方法是不會(huì)產(chǎn)生有效的結(jié)果的. 回調(diào)的回, 就體現(xiàn)在此處, 在 Store 類(lèi)之中的 returnOrderGoodsInfo(OrderResult order) 方法之中, 得到了很好的體現(xiàn).
/*同步,?顧客在商店預(yù)訂商品,?商店通知顧客預(yù)訂情況*/public?class?SyncBuyer?implements?OrderResult?{
????@Getter
????@Setter
????private?Store?store;//商店
????@Getter
????@Setter
????private?String?buyerName;//購(gòu)物者名
????@Getter
????@Setter
????private?String?goodsName;//所購(gòu)商品名
????SyncBuyer(Store?store,?String?buyerName,?String?goodsName)?{
????????this.store?=?store;
????????this.buyerName?=?buyerName;
????????this.goodsName?=?goodsName;
????}
????/*調(diào)用從商店返回訂購(gòu)物品的信息*/
????public?String?orderGoods()?{
????????String?goodsState?=?store.returnOrderGoodsInfo(this);
????????System.out.println(goodsState);
????????myFeeling();//?測(cè)試同步還是異步,?同步需要等待,?異步無(wú)需等待
????????return?goodsState;
????}
????public?void?myFeeling()?{
????????String[]?s?=?{"有點(diǎn)小激動(dòng)",?"很期待!",?"希望是個(gè)好貨!"};
????????Random?random?=?new?Random();
????????int?temp?=?random.nextInt(3);
????????System.out.println("我是"?+?this.getBuyerName()?+?",?我現(xiàn)在的感覺(jué):?"?+?s[temp]);
????}
????/*被回調(diào)的方法,?我們自己不去調(diào)用,?這個(gè)方法給出的結(jié)果,?是其他接口或者程序給我們的,?我們自己無(wú)法產(chǎn)生*/
????@Override
????public?String?getOrderResult(String?state)?{
????????return?"在"?+?this.getStore().getName()?+?"商店訂購(gòu)的"?+?this.getGoodsName()?+?"玩具,?目前的預(yù)訂狀態(tài)是:?"?+?state;
????}
}
Test2Callback 類(lèi), 測(cè)試同步回調(diào)的結(jié)果,
public?class?Test2Callback?{????public?static?void?main(String[]?args)?{
????????Store?wallMart?=?new?Store("沙中路沃爾瑪");
????????SyncBuyer?syncBuyer?=?new?SyncBuyer(wallMart,?"小明",?"超能鐵扇公主");
????????System.out.println(syncBuyer.orderGoods());
????}
}
異步回調(diào)
同步回調(diào)和異步回調(diào)的代碼層面的差別就是是否在我們調(diào)用第三方的 API 處, 為其開(kāi)辟一條新的線程, 其他并無(wú)差異。
例子
OrderResult 接口, 其中的方法 getOrderResult
public?interface?OrderResult?{????/**
?????*?訂購(gòu)貨物的狀態(tài)
?????*
?????*?@param?state
?????*?@return
?????*/
????//參數(shù)可以不用,?用不用按照自己的實(shí)際需求決定
????public?String?getOrderResult(String?state);
}
Store 類(lèi), 商店提供會(huì)無(wú)預(yù)定消息返回的接口, 回調(diào) OrderResult 接口的方法, 給其返回預(yù)訂商品的狀態(tài).
public?class?Store?{????@Getter
????@Setter
????private?String?name;
????Store(String?name)?{
????????this.name?=?name;
????}
????/*回調(diào)函數(shù),?將結(jié)構(gòu)傳給那個(gè)我們不能直接調(diào)用的方法,?然后獲取結(jié)果*/
????public?String?returnOrderGoodsInfo(OrderResult?order)?{
????????String[]?s?=?{"訂購(gòu)中...",?"訂購(gòu)失敗",?"即將發(fā)貨!",?"運(yùn)輸途中...",?"已在投遞"};
????????Random?random?=?new?Random();
????????int?temp?=?random.nextInt(5);
????????String?s1?=?s[temp];
????????return?order.getOrderResult(s1);
????}
}
NoSyncBuyer 類(lèi), 異步調(diào)用 Store 類(lèi)的 returnOrderGoodsInfo(OrderResult order) 方法, 來(lái)返回商品轉(zhuǎn)改的結(jié)果.
/*異步*/@Slf4j
public?class?NoSyncBuyer?implements?OrderResult?{
????@Getter
????@Setter
????private?Store?store;//商店
????@Getter
????@Setter
????private?String?buyerName;//購(gòu)物者名
????@Getter
????@Setter
????private?String?goodsName;//所購(gòu)商品名
????NoSyncBuyer(Store?store,?String?buyerName,?String?goodsName)?{
????????this.store?=?store;
????????this.buyerName?=?buyerName;
????????this.goodsName?=?goodsName;
????}
????/*調(diào)用從商店返回訂購(gòu)物品的信息*/
????public?String?orderGoods()?{
????????String?goodsState?=?"--";
????????MyRunnable?mr?=?new?MyRunnable();
????????Thread?t?=?new?Thread(mr);
????????t.start();
????????System.out.println(goodsState);
????????goodsState?=?mr.getResult();//?得到返回值
????????myFeeling();//?用來(lái)測(cè)試異步是不是還是按順序的執(zhí)行
????????return?goodsState;
????}
????public?void?myFeeling()?{
????????String[]?s?=?{"有點(diǎn)小激動(dòng)",?"很期待!",?"希望是個(gè)好貨!"};
????????Random?random?=?new?Random();
????????int?temp?=?random.nextInt(3);
????????System.out.println("我是"?+?this.getBuyerName()?+?",?我現(xiàn)在的感覺(jué):?"?+?s[temp]);
????}
????/*被回調(diào)的方法,?我們自己不去調(diào)用,?這個(gè)方法給出的結(jié)果,?是其他接口或者程序給我們的,?我們自己無(wú)法產(chǎn)生*/
????@Override
????public?String?getOrderResult(String?state)?{
????????return?"在"?+?this.getStore().getName()?+?"商店訂購(gòu)的"?+?this.getGoodsName()?+?"玩具,?目前的預(yù)訂狀態(tài)是:?"?+?state;
????}
????//?開(kāi)啟另一個(gè)線程,?但是沒(méi)有返回值,?怎么回事
????//?調(diào)試的時(shí)候,?等待一會(huì)兒,?還是可以取到值,?但不是立即取到,?在print顯示的時(shí)候,?卻是null,?需要注意?
????private?class?MyRunnable?implements?Runnable?{
????????@Getter
????????@Setter
????????private?String?result;
????????@Override
????????public?void?run()?{
????????????try?{
????????????????Thread.sleep(10000);
????????????????result?=?store.returnOrderGoodsInfo(NoSyncBuyer.this);//?匿名函數(shù)的時(shí)候,?無(wú)法return?返回值
????????????}?catch?(InterruptedException?e)?{
????????????????log.error("出大事了,?異步回調(diào)有問(wèn)題了",?e);
????????????}
????????}
????}
}
Test2Callback 類(lèi), 測(cè)試同步回調(diào)和異步回調(diào)的結(jié)果.
public?class?Test2Callback?{????public?static?void?main(String[]?args)?{
????????Store?wallMart?=?new?Store("沙中路沃爾瑪");
????????SyncBuyer?syncBuyer?=?new?SyncBuyer(wallMart,?"小明",?"超能鐵扇公主");
????????System.out.println(syncBuyer.orderGoods());
????????System.out.println("\n");
????????Store?lawson?=?new?Store("沙中路羅森便利店");
????????NoSyncBuyer?noSyncBuyer?=?new?NoSyncBuyer(lawson,?"cherry",?"變形金剛");
????????System.out.println(noSyncBuyer.orderGoods());
????}
}----------? END? ----------
推薦閱讀
CSS設(shè)計(jì)基礎(chǔ)--初識(shí)篇
Chrome 開(kāi)發(fā)者工具各種騷技巧 ! 你知道幾個(gè)?
SpringBoot:切面AOP實(shí)現(xiàn)權(quán)限校驗(yàn):實(shí)例演示與注解全解
帶你快速搭建Vue前端項(xiàng)目--Git篇
點(diǎn)個(gè)在看
你最好看
總結(jié)
以上是生活随笔為你收集整理的android 等待回调再返回结果_震惊!!只剩你还不懂Java回调机制了!的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: datagrid表头与数据列宽度不对齐_
- 下一篇: 三点到六点是几个小时_环卫工在10吨垃圾