1、線程
Flutter 主要分為三個(gè)核心模塊:
- Framework:基于Dart語言構(gòu)建的framework,包括了動(dòng)畫以及各種組件。
- Engine:基于 C/C++ 構(gòu)建的引擎,包括了 Skia 和 DartVM, 以及在不同平臺(tái)實(shí)現(xiàn)的 shell 層,Engine 通過封裝好的 Embedder API 去調(diào)用不同平臺(tái)的能力。
- Embedder:嵌入層,將Flutter嵌入到各個(gè)平臺(tái)上。Embedder 負(fù)責(zé)范圍包括原生平臺(tái)插件、線程管理、事件循環(huán)等。
Dart是單線程模型,但并沒有主線程/子線程之分,只有isolate,所有代碼都運(yùn)行在某個(gè)isolate中。
當(dāng)啟動(dòng)Flutter程序后后系統(tǒng)會(huì)創(chuàng)建一個(gè)isolate并初始化兩個(gè)事件隊(duì)列,一個(gè)是事件隊(duì)列(Event Queue )和微任務(wù)隊(duì)列( MicroTask Queue),初始化完成后會(huì)執(zhí)行main()方法,然后啟動(dòng)事件循環(huán)(Event Loop)。
1)isolate
所有的Dart代碼都是在isolate中運(yùn)行,每個(gè)isolate都有自己的私有內(nèi)存塊、事件循環(huán)和隊(duì)列。每個(gè)isolate都是相互隔離(獨(dú)立)的,并不像線程那樣可以共享內(nèi)存。
Isolate間可以一起工作的唯一方法是通過來回傳遞消息。一個(gè)isolate將消息發(fā)送到另一個(gè)isolate,接收者使用其Event looper處理該消息。
通過開啟多個(gè)isolate來實(shí)現(xiàn)類似多線程解決方案。
2)事件隊(duì)列和微任務(wù)隊(duì)列
事件隊(duì)列處理事件:I/O事件、手勢事件、繪圖、計(jì)時(shí)器、future事件以及isolate之間的message等。
微任務(wù)隊(duì)列處理事件:希望通過這個(gè)隊(duì)列來處理來的稍晚一些的事情,但是在下一個(gè)消息到來之前需要處理完的事情??梢酝ㄟ^scheduleMicrotask來調(diào)度。
注意:
Microtask一般用于非常短的內(nèi)部異步動(dòng)作,并且任務(wù)量非常少,如果微任務(wù)非常多,就會(huì)造成Event queue排不上隊(duì),會(huì)阻塞Event queue的執(zhí)行(如,用戶點(diǎn)擊沒有反應(yīng))。所以,大多數(shù)情況下優(yōu)先考慮使用Event queue,整個(gè)Flutter源代碼僅引用scheduleMicroTask()方法7次。
事件處理優(yōu)先級(jí):
app開始運(yùn)行時(shí),event loop優(yōu)先處理微任務(wù)隊(duì)列,直到微任務(wù)隊(duì)列為空的時(shí)候,再開始處理事件隊(duì)列。事件隊(duì)列不為空的話,一次只取一個(gè)event執(zhí)行,執(zhí)行完后會(huì)重新判斷microtask是否為空,不為空的話會(huì)接著回到微任務(wù)隊(duì)列循環(huán)以上操作。
2.異步操作實(shí)現(xiàn)
Dart是單線程語言,當(dāng)遇到延遲的運(yùn)算(I/O操作),線程中順序執(zhí)行的運(yùn)算就會(huì)阻塞,那就app上,用戶操作就會(huì)感到卡頓,于是通常用異步處理來解決這個(gè)問題,當(dāng)遇到需要延遲的運(yùn)算時(shí),就會(huì)放入延遲運(yùn)算的隊(duì)列中,先把不需要延遲的運(yùn)算先執(zhí)行,最后再來處理延遲運(yùn)算。
Dart類庫有非常多的返回Future或者Stream對象的函數(shù),這些函數(shù)被稱為異步函數(shù);
1)Future
Future,顧名思義,表示一件將來會(huì)發(fā)生的事情(也就是不會(huì)立即執(zhí)行),將來可以從Future中取到一個(gè)值,當(dāng)一個(gè)方法返回一個(gè)Future對象時(shí),發(fā)生兩件事:
- 這個(gè)方法將某件事情排隊(duì),返回一個(gè)未完成的Future。
- 這個(gè)方法事情完畢后,F(xiàn)uture的狀態(tài)會(huì)變成已經(jīng)完成,這個(gè)時(shí)候可以取到這件事情的返回值。
Future,顧名思義,表示一件將來會(huì)發(fā)生的事情(也就是不會(huì)立即執(zhí)行),將來可以從Future中取到一個(gè)值,當(dāng)一個(gè)方法返回一個(gè)Future的時(shí)候,發(fā)生兩件事:
- 這個(gè)方法將某件事情排隊(duì),返回一個(gè)未完成的Future對象。
- 這個(gè)方法事情完畢后,F(xiàn)uture的狀態(tài)會(huì)變成已經(jīng)完成,這個(gè)時(shí)候可以取到這件事情的返回值。
Future也可以這樣理解:
當(dāng)執(zhí)行到await...的時(shí)候,實(shí)際上返回的是一個(gè)延遲計(jì)算的Future對象,這個(gè)Future對象是Dart內(nèi)置的,有自己的隊(duì)列策略,它將要操作的事件放入EventQueue中,在隊(duì)列中的事件按照先進(jìn)先出的原則去逐一處理事件,當(dāng)事件處理完成后,將結(jié)果返回給Future對象。
Future 操作及異常捕獲:
示例:
void create(){
//延遲三秒執(zhí)行
var file = File("/Users/ywk/Desktop/flutter文本.rtf");
//定義了返回結(jié)果值為String類型
Future<String> data = file.readAsString();
//返回文件內(nèi)容
data.then((text){
//打印文件內(nèi)容
print(text);
});
print("I love iOS");
}
輸出:
I love iOS
···文件內(nèi)容···
--------------------------------
Future的異常捕獲和完成時(shí)調(diào)用:
Future.delayed(new Duration(seconds: 3),(){
throw AssertionError("This is a Error");
}).then((data){
//這是成功的邏輯
print("success");
},onError:(e){
//這是失敗的邏輯
print(e);
}).whenComplete((){
print("無論失敗,或者成功都會(huì)走到這");
});
}
Future 監(jiān)聽多個(gè)異步操作:
如有一個(gè)界面,需要從兩個(gè)接口獲取數(shù)據(jù),獲取成功后,將兩個(gè)數(shù)據(jù)進(jìn)行處理后顯示在UI界面上,這時(shí)候,F(xiàn)uture.wait派出用上了,它接收一個(gè)Future數(shù)組參數(shù),只有數(shù)組中所有的Future執(zhí)行成功后,就會(huì)觸發(fā)then回調(diào),當(dāng)然,只要有一個(gè)Future執(zhí)行失敗就會(huì)觸發(fā)錯(cuò)誤回調(diào)。
示例:
Future.wait([
Future.delayed(new Duration(seconds: 3),(){
return "異步操作1";
}),
Future.delayed(new Duration(seconds: 4),(){
return " 異步操作2";
})
]).then((data){
// 兩個(gè)異步操作都執(zhí)行成功后,data是個(gè)操作結(jié)果數(shù)組
print(data[0] + data[1]);
}).catchError((e){
//捕捉錯(cuò)誤
print(e);
});
}
當(dāng)兩個(gè)異步任務(wù)完成才會(huì)回調(diào)then函數(shù)。
2)async 和 await
使用Async/await也是可以實(shí)現(xiàn)異步操作
async 關(guān)鍵字:
- 當(dāng)使用async關(guān)鍵字作為方法聲明的后綴時(shí),該方法的返回值是一個(gè) Future。
- 它同步執(zhí)行該方法的代碼直到第一個(gè)await關(guān)鍵字,然后它暫停該方法其他部分的執(zhí)行。
- 一旦由await關(guān)鍵字引用的Future執(zhí)行完成,下一行代碼將立即執(zhí)行。
await 關(guān)鍵字:
- await只能在async函數(shù)中出現(xiàn)。
- async函數(shù)中可以出現(xiàn)多個(gè)await,每遇見一個(gè)就返回一個(gè)Future, 實(shí)際結(jié)果類似于用then串起來的回調(diào)。
- async函數(shù)也可以沒有await,在函數(shù)體同步執(zhí)行完畢以后返回一個(gè)Future。
示例:
foo() async {
print('foo E');
String value = await bar();
print('foo X $value');
}
bar() async {
print("bar E");
return "hello";
}
main() {
print('main E');
foo();
print("main X");
}
執(zhí)行結(jié)果:
main E
foo E
bar E
main X
foo X hello