Flutter--Future
什么是Future?
簡單來說future就是一個Future<T>對象,當執行return await。。。的時候,實際上返回的是一個延遲計算的Future對象,這個Future對象是Dart內置的,有自己的隊列策略,它將要操作的事件放入EventQueue中,在隊列中的事件按照先進先出的原則去逐一處理事件,當事件處理完成后,將結果返回給Future對象。
在這個過程中涉及到了異步和等待:
- 異步:就是不用阻塞當前線程,來等待該線程任務處理完成再去執行其他任務。
- 等待:await,聲明運算為延遲執行
async和await
首先看一個例子:
getData() async{
return await http.get(Uri.encodeFull(url), headers: {"Accept": "application/json"});
}
//然后調用函數來獲取結果
String data = getData();
這段代碼在運行的時候會報錯。
因為data
是String
類型,而函數getData()
是一個異步操作函數,其返回值是一個await
延遲執行的結果。
在Dart
中,有await
標記的運算,結果都是一個Future
對象,Future
不是String
類型,所以就報錯了。
如何獲取異步函數的結果呢?Dart
規定有async
標記的函數,只能由await
來調用,那么我們可以在函數前加一個await
關鍵字:
String data = await getData();
但是這違背了await
必須要在async
標記的函數中使用,所以賦值代碼可以改成:
String data;
setData() async {
data = await getData(); //getData()延遲執行后賦值給data
}
總結:
async
和await
的使用其實就只有兩點:
-
await
關鍵字必須在async
函數內部使用 - 調用
async
函數必須使用await
關鍵字
Dart異步
Dart是單線程模型,是一種Event-Looper以及Event-Queue的模型,所有的事件都是通過EventLooper的依次執行。
Event Loop的執行順序
- 從EventQueue中獲取Event
-
處理Event直到EventQueue為空
Event即事件,包括輸入,點擊,Timer,文件IO等
單線程模型
所謂單線程,就是一旦一個函數開始執行,就必須將這個函數執行完,才能去執行其他函數。
Dart中沒有線程的概念,只有isolate,每個isolate都是隔離的,并不會共享內存。一個Dart程序是在Main isolate中的main函數開始,而在Main函數結束后,Main isolate線程開始一個個(one by one)的處理Event Queue中的每一個Event。
Event Queue、Microtask Queue
Dart中的Main Isolate只有一個Event Looper,但是存在兩個Event Queue:
- Event Queue
-
Microtask Queue
這兩者之間的關系可以用一張圖來說明:
- Microtask Queue中的Event優先被處理
- 直到Microtask Queue隊列中的Event為空時,才會去執行Event Queue中的Event
異步任務調度
當有代碼可以在后續任務執行的時候,有兩種方式,通過dart:async這個Lib中的API即可:
- 使用Future類,可以將任務加入到Event Queue的隊尾
- 使用scheduleMicrotask函數,將任務加入到Microtask Queue隊尾
當使用EventQueue時,需要考慮清楚,盡量避免microtask queue過于龐大,否則會阻塞其他事件的處理
Future的使用
一般常用的Future構造函數:
new Future((){
// doing something
});
而一般常用的還有當有分治任務時,需要將一個大任務拆成很多小任務一步步執行時,就需要使用到Future.then函數來拆解任務:
void main(){
new Future(() => futureTask) // 異步任務的函數
.then((m) => "futueTask execute result:$m") // 任務執行完后的子任務
.then((m) => m.length) // 其中m為上個任務執行完后的返回的結果
.then((m) => printLength(m))
.whenComplete(() => whenTaskCompelete); // 當所有任務完成后的回調函數
}
int futureTask() {
return 21;
}
void printLength(int length) {
print("Text Length:$length");
}
void whenTaskCompelete() {
print("Task Complete");
}
當任務需要延遲執行時,可以使用new Future.delay來將任務延遲執行,而如上所述,只有當Main isolate的Event Queue處于Idle的狀態時,才會延遲1s執行,否則等待的時間會比1s長很多
new Future.delayed(const Duration(seconds: 1), () => futureTask);
Tips
-
Future
中的then
并沒有創建新的Event
丟到Event Queue
中,而只是一個普通的Function Call
,在FutureTask
執行完后,立即開始執行 - 當
Future
在then
函數先已經執行完成了,則會創建一個task
,將該task
的添加到microtask queue
中,并且該任務將會執行通過then
傳入的函數 -
Future
只是創建了一個Event
,將Event
插入到了Event Queue
的隊尾 - 使用
Future.value
構造函數的時候,就會和第二條一樣,創建Task
丟到microtask Queue
中執行then
傳入的函數 -
Future.sync
構造函數執行了它傳入的函數之后,也會立即創建Task
丟到microtask Queue
中執行
關于Future的原理基本就到這里了~~~