Dart是一個單線程語言,能夠理解成物理線路中的串聯,當其遇到有延遲的運算(好比IO操做、延時執行)時,線程中按順序執行的運算就會阻塞,用戶就會感受到卡頓,因而一般用異步處理來解決這個問題。編程
Dart異步編程有兩種方式:Future和Streamjson
Future至關於40米大砍刀,Stream至關於一捆40米大砍刀。dart提供了關鍵字async(異步)和await(延遲執行),至關於普通的便捷的小匕首,而小匕首是咱們平時常常用到的。api
當遇到有須要延遲的運算(async)時,將其放入到延遲運算的隊列(await)中去,把不須要延遲運算的部分先執行掉,最後再來處理延遲運算的部分。app
async await 這兩個關鍵字是dart語言的特性,能讓你寫出看起來像是「同步」的「異步」代碼,先看一個方法案例:異步
/*HTTP的get請求返回值爲Future<String>類型,即其返回值將來是一個String類型的值*/ /*async關鍵字聲明該函數內部有代碼須要延遲執行*/ getData() async { /*await關鍵字聲明運算爲延遲執行,而後return運算結果*/ return await http.get(Uri.encodeFull(url), headers: {"Accept": "application/json"}); }
而後咱們嘗試調用這個方法,並獲取返回值。async
String data = getDate();
而後控制檯報錯了….ide
爲何呢?由於data是String類型,而函數getData()是一個異步操做函數,其返回值是一個await延遲執行的結果。在Dart中,有await標記的運算,其結果值都是一個Future對象,Future不是String類型,因此就報錯了。異步編程
總結一下:函數
在請求方法中直接 return await .. .的時候,實際上返回的是一個延遲計算的Future對象。url
還有兩點須要注意:
就是說:
1.要想 return await … ,那麼方法首先是 async 的,如上方方法。
2.使用 async 標註的方法,必需要用 await 接收返回值,好比上方方法在接收返回值時,須要加入 await
var data = await getData();
Future表示一件「未來」會發生的事情,未來能夠從Future中取到一個值。當一個方法返回一個Future的事情,發生兩件事情:
要取到這個「返回值」,有兩種方式:
咱們看這兩種實現方式的案例:
先看個案例,等待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.117136
what?
很明顯,打印結果並無按照串聯的方式依次打印。
flutter中會改造帶asyc關鍵字的方法,讓這個方法脫離主流程,變成「後面一點」執行(經過scheduleMicrotask),因此可讓咱們的程序「看起來」是順序執行的。
咱們修改一下 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這個方法。
在請求方法中直接 return await .. .的時候,實際上返回的是一個延遲計算的Future對象。
有兩點須要注意:
Flutter 中有兩種實現異步編程的方式:Future api、 async await
平常開發中經常使用的是 async await Future 搭配。