flutter中的异步机制Future
餓補(bǔ)一下Flutter中Http請(qǐng)求的異步操作。
Dart是一個(gè)單線程語(yǔ)言,可以理解成物理線路中的串聯(lián),當(dāng)其遇到有延遲的運(yùn)算(比如IO操作、延時(shí)執(zhí)行)時(shí),線程中按順序執(zhí)行的運(yùn)算就會(huì)阻塞,用戶就會(huì)感覺到卡頓,于是通常用異步處理來(lái)解決這個(gè)問(wèn)題。
Dart異步編程有兩種方式:Future和Stream
Future相當(dāng)于40米大砍刀,Stream相當(dāng)于一捆40米大砍刀。dart提供了關(guān)鍵字async(異步)和await(延遲執(zhí)行),相當(dāng)于普通的便捷的小匕首,而小匕首是我們平時(shí)經(jīng)常用到的。
當(dāng)遇到有需要延遲的運(yùn)算(async)時(shí),將其放入到延遲運(yùn)算的隊(duì)列(await)中去,把不需要延遲運(yùn)算的部分先執(zhí)行掉,最后再來(lái)處理延遲運(yùn)算的部分。
1、async和await
async await 這兩個(gè)關(guān)鍵字是dart語(yǔ)言的特性,能讓你寫出看起來(lái)像是“同步”的“異步”代碼,先看一個(gè)方法案例:
??/*HTTP的get請(qǐng)求返回值為Future<String>類型,即其返回值未來(lái)是一個(gè)String類型的值*//*async關(guān)鍵字聲明該函數(shù)內(nèi)部有代碼需要延遲執(zhí)行*/getData()?async?{????/*await關(guān)鍵字聲明運(yùn)算為延遲執(zhí)行,然后return運(yùn)算結(jié)果*/return?await?http.get(Uri.encodeFull(url),?headers:?{"Accept":?"application/json"});?}然后我們嘗試調(diào)用這個(gè)方法,并獲取返回值。
String?data?=?getDate();然后控制臺(tái)報(bào)錯(cuò)了….
為什么呢?因?yàn)閐ata是String類型,而函數(shù)getData()是一個(gè)異步操作函數(shù),其返回值是一個(gè)await延遲執(zhí)行的結(jié)果。在Dart中,有await標(biāo)記的運(yùn)算,其結(jié)果值都是一個(gè)Future對(duì)象,Future不是String類型,所以就報(bào)錯(cuò)了。
總結(jié)一下:
在請(qǐng)求方法中直接 return await .. .的時(shí)候,實(shí)際上返回的是一個(gè)延遲計(jì)算的Future對(duì)象。
還有兩點(diǎn)需要注意:
- await關(guān)鍵字必須在async函數(shù)內(nèi)部使用
- 調(diào)用async函數(shù)必須使用await關(guān)鍵字
后面兩點(diǎn)怎么講?
2、什么是Future
Future表示一件“將來(lái)”會(huì)發(fā)生的事情,將來(lái)可以從Future中取到一個(gè)值。當(dāng)一個(gè)方法返回一個(gè)Future的事情,發(fā)生兩件事情:
- 這個(gè)方法將某件事情排隊(duì),返回一個(gè)未完成的Future
- 當(dāng)這件事情完畢之后,Future的狀態(tài)會(huì)變成已完成,這個(gè)時(shí)候就可以取到這件事情的返回值了。
要取到這個(gè)“返回值”,有兩種方式:
- 使用async配合await
- 使用Future提供的api
我們看這兩種實(shí)現(xiàn)方式的案例:
2.1、使用async配合await
先看個(gè)案例,等待3秒后返回‘我是用戶’:
/*模擬異步加載用戶信息*/ Future?_getUserInfo()?async{await?new?Future.delayed(new?Duration(milliseconds:?3000));return?"我是用戶"; }/*加載用戶信息,順便打印時(shí)間看看順序*/ Future?_loadUserInfo()?async{print("_loadUserInfo:${new?DateTime.now()}");print(await?_getUserInfo());print("_loadUserInfo:${new?DateTime.now()}"); }我們?cè)趇nitState中調(diào)用該方法:
@override void?initState(){print("initState:${new?DateTime.now()}");_loadUserInfo();print("initState:${new?DateTime.now()}");super.initState(); }打印結(jié)果如下:
I/flutter?(?1802):?initState:2019-06-20?09:46:40.097339 I/flutter?(?1802):?_loadUserInfo:2019-06-20?09:46:40.103542 I/flutter?(?1802):?Instance?of?'Future<dynamic>' I/flutter?(?1802):?initState:2019-06-20?09:46:40.108510 I/flutter?(?1802):?我是用戶 I/flutter?(?1802):?_loadUserInfo:2019-06-20?09:46:43.117136what?
很明顯,打印結(jié)果并沒(méi)有按照串聯(lián)的方式依次打印。
flutter中會(huì)改造帶asyc關(guān)鍵字的方法,讓這個(gè)方法脫離主流程,變成“后面一點(diǎn)”執(zhí)行(通過(guò)scheduleMicrotask),所以可以讓我們的程序“看起來(lái)”是順序執(zhí)行的。
2.2、Future api
我們修改一下 loadUserInfo() 方法:
/*加載用戶信息,順便打印時(shí)間看看順序*/Future?_loadUserInfo()?async{print("_loadUserInfo:${new?DateTime.now()}");_getUserInfo().then((info){print(info);});print("_loadUserInfo:${new?DateTime.now()}");}再次運(yùn)行輸出一下:
I/flutter?(?1802):?initState:2019-06-20?09:50:32.488765 I/flutter?(?1802):?_loadUserInfo:2019-06-20?09:50:32.494751 I/flutter?(?1802):?_loadUserInfo:2019-06-20?09:50:32.499725 I/flutter?(?1802):?Instance?of?'Future<dynamic>' I/flutter?(?1802):?initState:2019-06-20?09:50:32.499970 I/flutter?(?1802):?我是用戶兩次輸出是有不同的,主要不同在于第二個(gè) loadUserInfo 的日志打印,與‘我是用戶’的輸出順序,為什么有差異?
await會(huì)阻塞流程,等待緊跟著的的Future執(zhí)行完畢之后,再執(zhí)行下一條語(yǔ)句,而如果用了Future.then這個(gè)api,那么就不會(huì)等待,直接執(zhí)行下面的語(yǔ)句,等Future執(zhí)行完了,再調(diào)用then這個(gè)方法。
3、總結(jié)
在請(qǐng)求方法中直接 return await .. .的時(shí)候,實(shí)際上返回的是一個(gè)延遲計(jì)算的Future對(duì)象。
有兩點(diǎn)需要注意:
- await關(guān)鍵字必須在async函數(shù)內(nèi)部使用
- 調(diào)用async函數(shù)必須使用await關(guān)鍵字
Flutter 中有兩種實(shí)現(xiàn)異步編程的方式:Future api、 async await
日常開發(fā)中常用的是 async await Future 搭配。
創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎(jiǎng)勵(lì)來(lái)咯,堅(jiān)持創(chuàng)作打卡瓜分現(xiàn)金大獎(jiǎng)總結(jié)
以上是生活随笔為你收集整理的flutter中的异步机制Future的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 《金字塔原理》学习笔记 | 第4篇—演示
- 下一篇: Node.js中使用AWS SNS服务发