Flutter-線程與異步

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 

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容