關(guān)于Dart中的異步編程
一 事件循環(huán)
flutter 就是運行在一個root isolate 中
程序只要運行起來,就有一個事件循環(huán)一直在運行 ,直至程序退出。
EventLoop 先從mrcro 對列中取任務(wù),取完任務(wù)再去 event 隊列中取任務(wù)。隊列任務(wù)是FIFO。
二 認(rèn)識Future
abstract class Future<T>
Future 是Dart 中提供的一個抽象類,泛型類,它用于封裝一段在將來會被執(zhí)行的代碼邏輯。
Future就是異步中非常重要的角色。Future表示異步返回的結(jié)果,當(dāng)執(zhí)行一個異步延遲的計算時候,首先會返回一個Future結(jié)果,后續(xù)代碼可以繼續(xù)執(zhí)行不會阻塞主isolate,當(dāng)Future中的計算結(jié)果到達時,如果注冊了 then
函數(shù)回調(diào),對于返回成功的回調(diào)就會拿到最終計算的值,對于返回失敗的回調(diào)就會拿到一個異常信息
1 基本使用
Flutter提供了下面三個方法,讓我們來注冊回調(diào),來監(jiān)聽處理Future的結(jié)果。
//處理完成時候的回調(diào),一般都是成功回調(diào) Future<R> then<R>(FutureOr<R> onValue(T value), {Function onError}); //處理失敗的回調(diào),比如throw一個error就會走到這里 Future<T> catchError(Function onError, {bool test(Object error)}); //Future.whenComplete總是在Future完成后調(diào)用,不管Future的結(jié)果是正確的還是錯誤的。 Future<T> whenComplete(FutureOr action());
代碼示例:
import 'dart:io'; main(List<String> args) { // 阻塞主線程的調(diào)用 // blockMainThread(); // 異步調(diào)用 asyncMethod(); } /*****----- 異步的調(diào)用方式 ---***/ void asyncMethod() { /** * main start main end hello world * */ print("main start"); var future = getAsyncNetworkData(); future.then((String value) { // 只有拿到結(jié)果 才會執(zhí)行這里面的代碼 print(value); }).catchError((error) { // 打印結(jié)果 Exception: 我是錯誤信息 print(error); }).whenComplete(() { // 代碼走這,不管成功或者失敗都會走這里 print("代碼執(zhí)行完畢"); }); print("main end"); } Future<String> getAsyncNetworkData() { return Future<String>(() { sleep(Duration(seconds: 3)); // return "hello world"; // 拋出異常 throw Exception("我是錯誤信息"); }); } /*****----- 阻塞主線程的調(diào)用方式 ---***/ void blockMainThread() { /** * main start this is hello world main end * */ print("main start"); var res = getNetworkData(); print(res); print("main end"); } // 模擬網(wǎng)絡(luò)請求 String getNetworkData() { // 阻塞2秒 sleep(Duration(seconds: 2)); return "this is hello world"; }
2 鏈?zhǔn)秸{(diào)用
鏈?zhǔn)秸{(diào)用優(yōu)勢在于可以明確代碼執(zhí)行前后依賴關(guān)系以及實現(xiàn)異常的捕獲
import 'dart:io'; main(List<String> args) { print("main start"); /** * main start main end 第一次網(wǎng)絡(luò)請求的結(jié)果 第二次網(wǎng)路請求的結(jié)果 第三次網(wǎng)路請求的結(jié)果 * * */ // 這種方式可以解決回調(diào)地獄的問題 多個網(wǎng)絡(luò)請求依賴也不用進行嵌套調(diào)用 直接鏈?zhǔn)秸{(diào)用即可 Future(() { // 這是第一次網(wǎng)絡(luò)請求 sleep(Duration(seconds: 2)); return "第一次網(wǎng)絡(luò)請求的結(jié)果"; }) .then((res) { print(res); sleep(Duration(seconds: 2)); // 這是第二次網(wǎng)絡(luò)請求 return "第二次網(wǎng)路請求的結(jié)果"; }) .then((res) { print(res); sleep(Duration(seconds: 2)); return "第三次網(wǎng)路請求的結(jié)果"; }) .then((value) => print(value)) .catchError((error) { print(error); }); print("main end"); }
三 await 和 async
要定義異步函數(shù),請在函數(shù)主體之前添加async關(guān)鍵字,他倆是配對出現(xiàn)的
他們是dart 語言中的關(guān)鍵字,最為重要的使用就是
可以讓我們用同步的代碼格式去實現(xiàn)異步的調(diào)用過程。
大部分Future使用的場景都可以使用async-await來替代,也建議使用async-await。
下面有這樣一個需求 :比如說用戶登錄完成之后,拿到用戶的token 去請求數(shù)據(jù),就是請求之間的依賴
用 await async 方式實現(xiàn) 和 Future 實現(xiàn)比較
import 'dart:io'; main(List<String> args) { print("main start"); // getData(); futureMethodData(); print("main end"); } // future 的實現(xiàn)方式 futureMethodData() { Future(() { // 這是第一次網(wǎng)絡(luò)請求 sleep(Duration(seconds: 2)); return "這是第一次網(wǎng)絡(luò)請求結(jié)果"; }).then((value) { print(value); sleep(Duration(seconds: 2)); return value + "這是第二次網(wǎng)絡(luò)請求結(jié)果"; }).then((value) { print(value); sleep(Duration(seconds: 2)); return value + "這是第三次網(wǎng)絡(luò)請求結(jié)果"; }).then((value) { print(value); }); } // async-await 的實現(xiàn)方式 getData() async { // 模擬三次網(wǎng)絡(luò)請求 /** * * main start main end args1helloworld args1helloworldhelloworld args1helloworldhelloworldhelloworld */ var res1 = await getNetworkData("args1"); print(res1); var res2 = await getNetworkData(res1); print(res2); var res3 = await getNetworkData(res2); print(res3); } getNetworkData(String args) { return Future(() { sleep(Duration(seconds: 2)); return args + "helloworld"; }); }
四 isolate
isolate 可以理解為dart 中的多線程,現(xiàn)在設(shè)備基本都是多核CPU,可以使用isolate 充分利用硬件資源。
isolate 之間是獨立的,資源不共享的。每一個isaolate 都有自己的事件循環(huán)以及隊列。
1 使用
import 'dart:io'; import 'dart:isolate'; main(List<String> args) async { print("main start"); // 1 ReceivePort receivePort = ReceivePort(); // 2 spawn 返回的是future 所以要異步操作 Isolate isolate = await Isolate.spawn<SendPort>(calculate, receivePort.sendPort); // 可以給創(chuàng)建的isolate 中發(fā)送消息 receivePort.sendPort.send("這是從main isolate 發(fā)送的消息"); //3 監(jiān)聽創(chuàng)建的isolate的回調(diào)信息 receivePort.listen((message) { print(message); // 收到結(jié)果 關(guān)閉 kill receivePort.close(); isolate.kill(); }); print("main end"); } calculate(SendPort port) { // 模擬耗時操作 sleep(Duration(seconds: 2)); // 回調(diào)信息 port.send("這是從創(chuàng)建的isolate 發(fā)送的信息"); }
到此這篇關(guān)于關(guān)于Dart中的異步編程的文章就介紹到這了,更多相關(guān)Dart中的異步內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Flutter SizedBox布局組件Widget使用示例詳解
這篇文章主要為大家介紹了Flutter SizedBox布局組件Widget使用示例詳解2023-02-02Flutter入門學(xué)習(xí)Dart語言變量及基本使用概念
這篇文章主要為大家介紹了Flutter入門學(xué)習(xí)Dart語言變量及基本使用概念,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2022-09-09