這篇文章主要介紹了關(guān)于Dart中的異步編程,dart 是強(qiáng)類型語言,但由于具備類型推導(dǎo)功能所以類型聲明是可選的,需要的朋友可以參考下
一 事件循環(huán)
flutter 就是運(yùn)行在一個(gè)root isolate 中
程序只要運(yùn)行起來,就有一個(gè)事件循環(huán)一直在運(yùn)行 ,直至程序退出。
EventLoop 先從mrcro 對(duì)列中取任務(wù),取完任務(wù)再去 event 隊(duì)列中取任務(wù)。隊(duì)列任務(wù)是FIFO。
[圖片上傳失敗...(image-d055d-1692084277064)]
二 認(rèn)識(shí)Future
abstract class Future<T>
Future 是Dart 中提供的一個(gè)抽象類,泛型類,它用于封裝一段在將來會(huì)被執(zhí)行的代碼邏輯。
Future就是異步中非常重要的角色。Future表示異步返回的結(jié)果,當(dāng)執(zhí)行一個(gè)異步延遲的計(jì)算時(shí)候,首先會(huì)返回一個(gè)Future結(jié)果,后續(xù)代碼可以繼續(xù)執(zhí)行不會(huì)阻塞主isolate,當(dāng)Future中的計(jì)算結(jié)果到達(dá)時(shí),如果注冊(cè)了 then 函數(shù)回調(diào),對(duì)于返回成功的回調(diào)就會(huì)拿到最終計(jì)算的值,對(duì)于返回失敗的回調(diào)就會(huì)拿到一個(gè)異常信息
1、 基本使用
Flutter提供了下面三個(gè)方法,讓我們來注冊(cè)回調(diào),來監(jiān)聽處理Future的結(jié)果。
//處理完成時(shí)候的回調(diào),一般都是成功回調(diào)
Future<R> then<R>(FutureOr<R> onValue(T value), {Function onError});
//處理失敗的回調(diào),比如throw一個(gè)error就會(huì)走到這里
Future<T> catchError(Function onError, {bool test(Object error)});
//Future.whenComplete總是在Future完成后調(diào)用,不管Future的結(jié)果是正確的還是錯(cuò)誤的。
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é)果 才會(huì)執(zhí)行這里面的代碼
print(value);
}).catchError((error) {
// 打印結(jié)果 Exception: 我是錯(cuò)誤信息
print(error);
}).whenComplete(() {
// 代碼走這,不管成功或者失敗都會(huì)走這里
print("代碼執(zhí)行完畢");
});
print("main end");
}
Future<String> getAsyncNetworkData() {
return Future<String>(() {
sleep(Duration(seconds: 3));
// return "hello world";
// 拋出異常
throw Exception("我是錯(cuò)誤信息");
});
}
/*****----- 阻塞主線程的調(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ò)請(qǐng)求
String getNetworkData() {
// 阻塞2秒
sleep(Duration(seconds: 2));
return "this is hello world";
}
2 、鏈?zhǔn)秸{(diào)用
鏈?zhǔn)秸{(diào)用優(yōu)勢(shì)在于可以明確代碼執(zhí)行前后依賴關(guān)系以及實(shí)現(xiàn)異常的捕獲
import 'dart:io';
main(List<String> args) {
print("main start");
/**
* main start
main end
第一次網(wǎng)絡(luò)請(qǐng)求的結(jié)果
第二次網(wǎng)路請(qǐng)求的結(jié)果
第三次網(wǎng)路請(qǐng)求的結(jié)果
*
* */
// 這種方式可以解決回調(diào)地獄的問題 多個(gè)網(wǎng)絡(luò)請(qǐng)求依賴也不用進(jìn)行嵌套調(diào)用 直接鏈?zhǔn)秸{(diào)用即可
Future(() {
// 這是第一次網(wǎng)絡(luò)請(qǐng)求
sleep(Duration(seconds: 2));
return "第一次網(wǎng)絡(luò)請(qǐng)求的結(jié)果";
})
.then((res) {
print(res);
sleep(Duration(seconds: 2));
// 這是第二次網(wǎng)絡(luò)請(qǐng)求
return "第二次網(wǎng)路請(qǐng)求的結(jié)果";
})
.then((res) {
print(res);
sleep(Duration(seconds: 2));
return "第三次網(wǎng)路請(qǐng)求的結(jié)果";
})
.then((value) => print(value))
.catchError((error) {
print(error);
});
print("main end");
}
三 、await 和 async
要定義異步函數(shù),請(qǐng)?jiān)诤瘮?shù)主體之前添加async關(guān)鍵字,他倆是配對(duì)出現(xiàn)的
他們是dart 語言中的關(guān)鍵字,最為重要的使用就是
可以讓我們用同步的代碼格式去實(shí)現(xiàn)異步的調(diào)用過程。
大部分Future使用的場(chǎng)景都可以使用async-await來替代,也建議使用async-await。
下面有這樣一個(gè)需求 :比如說用戶登錄完成之后,拿到用戶的token 去請(qǐng)求數(shù)據(jù),就是請(qǐng)求之間的依賴
用 await async 方式實(shí)現(xiàn) 和 Future 實(shí)現(xiàn)比較
import 'dart:io';
main(List<String> args) {
print("main start");
// getData();
futureMethodData();
print("main end");
}
// future 的實(shí)現(xiàn)方式
futureMethodData() {
Future(() {
// 這是第一次網(wǎng)絡(luò)請(qǐng)求
sleep(Duration(seconds: 2));
return "這是第一次網(wǎng)絡(luò)請(qǐng)求結(jié)果";
}).then((value) {
print(value);
sleep(Duration(seconds: 2));
return value + "這是第二次網(wǎng)絡(luò)請(qǐng)求結(jié)果";
}).then((value) {
print(value);
sleep(Duration(seconds: 2));
return value + "這是第三次網(wǎng)絡(luò)請(qǐng)求結(jié)果";
}).then((value) {
print(value);
});
}
// async-await 的實(shí)現(xiàn)方式
getData() async {
// 模擬三次網(wǎng)絡(luò)請(qǐng)求
/**
*
* 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 之間是獨(dú)立的,資源不共享的。每一個(gè)isaolate 都有自己的事件循環(huán)以及隊(duì)列。
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) {
// 模擬耗時(shí)操作
sleep(Duration(seconds: 2));
// 回調(diào)信息
port.send("這是從創(chuàng)建的isolate 發(fā)送的信息");
}
轉(zhuǎn)自:https://www.jb51.net/article/280919.htm