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