Flutter--Future
什么是Future?
簡單來說future就是一個(gè)Future<T>對象,當(dāng)執(zhí)行return await嚷闭。。赖临。的時(shí)候胞锰,實(shí)際上返回的是一個(gè)延遲計(jì)算的Future對象,這個(gè)Future對象是Dart內(nèi)置的兢榨,有自己的隊(duì)列策略嗅榕,它將要操作的事件放入EventQueue中,在隊(duì)列中的事件按照先進(jìn)先出的原則去逐一處理事件吵聪,當(dāng)事件處理完成后凌那,將結(jié)果返回給Future對象。
在這個(gè)過程中涉及到了異步和等待:
- 異步:就是不用阻塞當(dāng)前線程吟逝,來等待該線程任務(wù)處理完成再去執(zhí)行其他任務(wù)帽蝶。
- 等待:await,聲明運(yùn)算為延遲執(zhí)行
async和await
首先看一個(gè)例子:
getData() async{
return await http.get(Uri.encodeFull(url), headers: {"Accept": "application/json"});
}
//然后調(diào)用函數(shù)來獲取結(jié)果
String data = getData();
這段代碼在運(yùn)行的時(shí)候會報(bào)錯(cuò)块攒。
因?yàn)?code>data是String
類型励稳,而函數(shù)getData()
是一個(gè)異步操作函數(shù),其返回值是一個(gè)await
延遲執(zhí)行的結(jié)果局蚀。
在Dart
中麦锯,有await
標(biāo)記的運(yùn)算,結(jié)果都是一個(gè)Future
對象琅绅,Future
不是String
類型扶欣,所以就報(bào)錯(cuò)了。
如何獲取異步函數(shù)的結(jié)果呢千扶?Dart
規(guī)定有async
標(biāo)記的函數(shù)料祠,只能由await
來調(diào)用,那么我們可以在函數(shù)前加一個(gè)await
關(guān)鍵字:
String data = await getData();
但是這違背了await
必須要在async
標(biāo)記的函數(shù)中使用澎羞,所以賦值代碼可以改成:
String data;
setData() async {
data = await getData(); //getData()延遲執(zhí)行后賦值給data
}
總結(jié):
async
和await
的使用其實(shí)就只有兩點(diǎn):
-
await
關(guān)鍵字必須在async
函數(shù)內(nèi)部使用 - 調(diào)用
async
函數(shù)必須使用await
關(guān)鍵字
Dart異步
Dart是單線程模型髓绽,是一種Event-Looper以及Event-Queue的模型,所有的事件都是通過EventLooper的依次執(zhí)行妆绞。
Event Loop的執(zhí)行順序
- 從EventQueue中獲取Event
-
處理Event直到EventQueue為空
Event即事件顺呕,包括輸入,點(diǎn)擊括饶,Timer株茶,文件IO等
單線程模型
所謂單線程,就是一旦一個(gè)函數(shù)開始執(zhí)行图焰,就必須將這個(gè)函數(shù)執(zhí)行完启盛,才能去執(zhí)行其他函數(shù)。
Dart中沒有線程的概念,只有isolate僵闯,每個(gè)isolate都是隔離的卧抗,并不會共享內(nèi)存。一個(gè)Dart程序是在Main isolate中的main函數(shù)開始鳖粟,而在Main函數(shù)結(jié)束后社裆,Main isolate線程開始一個(gè)個(gè)(one by one)的處理Event Queue中的每一個(gè)Event。
Event Queue牺弹、Microtask Queue
Dart中的Main Isolate只有一個(gè)Event Looper浦马,但是存在兩個(gè)Event Queue:
- Event Queue
-
Microtask Queue
這兩者之間的關(guān)系可以用一張圖來說明:
- Microtask Queue中的Event優(yōu)先被處理
- 直到Microtask Queue隊(duì)列中的Event為空時(shí),才會去執(zhí)行Event Queue中的Event
異步任務(wù)調(diào)度
當(dāng)有代碼可以在后續(xù)任務(wù)執(zhí)行的時(shí)候张漂,有兩種方式晶默,通過dart:async這個(gè)Lib中的API即可:
- 使用Future類,可以將任務(wù)加入到Event Queue的隊(duì)尾
- 使用scheduleMicrotask函數(shù)航攒,將任務(wù)加入到Microtask Queue隊(duì)尾
當(dāng)使用EventQueue時(shí)磺陡,需要考慮清楚,盡量避免microtask queue過于龐大漠畜,否則會阻塞其他事件的處理
Future的使用
一般常用的Future構(gòu)造函數(shù):
new Future((){
// doing something
});
而一般常用的還有當(dāng)有分治任務(wù)時(shí)币他,需要將一個(gè)大任務(wù)拆成很多小任務(wù)一步步執(zhí)行時(shí),就需要使用到Future.then函數(shù)來拆解任務(wù):
void main(){
new Future(() => futureTask) // 異步任務(wù)的函數(shù)
.then((m) => "futueTask execute result:$m") // 任務(wù)執(zhí)行完后的子任務(wù)
.then((m) => m.length) // 其中m為上個(gè)任務(wù)執(zhí)行完后的返回的結(jié)果
.then((m) => printLength(m))
.whenComplete(() => whenTaskCompelete); // 當(dāng)所有任務(wù)完成后的回調(diào)函數(shù)
}
int futureTask() {
return 21;
}
void printLength(int length) {
print("Text Length:$length");
}
void whenTaskCompelete() {
print("Task Complete");
}
當(dāng)任務(wù)需要延遲執(zhí)行時(shí)憔狞,可以使用new Future.delay來將任務(wù)延遲執(zhí)行蝴悉,而如上所述,只有當(dāng)Main isolate的Event Queue處于Idle的狀態(tài)時(shí)瘾敢,才會延遲1s執(zhí)行拍冠,否則等待的時(shí)間會比1s長很多
new Future.delayed(const Duration(seconds: 1), () => futureTask);
Tips
-
Future
中的then
并沒有創(chuàng)建新的Event
丟到Event Queue
中,而只是一個(gè)普通的Function Call
簇抵,在FutureTask
執(zhí)行完后庆杜,立即開始執(zhí)行 - 當(dāng)
Future
在then
函數(shù)先已經(jīng)執(zhí)行完成了,則會創(chuàng)建一個(gè)task
碟摆,將該task
的添加到microtask queue
中晃财,并且該任務(wù)將會執(zhí)行通過then
傳入的函數(shù) -
Future
只是創(chuàng)建了一個(gè)Event
,將Event
插入到了Event Queue
的隊(duì)尾 - 使用
Future.value
構(gòu)造函數(shù)的時(shí)候典蜕,就會和第二條一樣断盛,創(chuàng)建Task
丟到microtask Queue
中執(zhí)行then
傳入的函數(shù) -
Future.sync
構(gòu)造函數(shù)執(zhí)行了它傳入的函數(shù)之后,也會立即創(chuàng)建Task
丟到microtask Queue
中執(zhí)行
關(guān)于Future的原理基本就到這里了~~~