Flutter開發(fā)進(jìn)階:Flutter事件循環(huán)機(jī)制與異步

Dart是基于 事件循環(huán)機(jī)制的單線程模型, 所以Dart中沒有多線程, 也就沒有主線程與子線程之分。

  • 單線程模型:一條執(zhí)行線上同時(shí)只能執(zhí)行一個(gè)任務(wù)炊甲,如果有耗時(shí)任務(wù)則需要放入隊(duì)列異步執(zhí)行卿啡。
  • 多線程:充分利用處理器的多核優(yōu)勢(shì)進(jìn)行并行計(jì)算。

一颈娜、事件循環(huán)機(jī)制

對(duì)于用戶點(diǎn)擊, 滑動(dòng), 硬盤IO訪問等事件, 你不知道何時(shí)發(fā)生或以什么順序發(fā)生, 所以得有一個(gè)永不停歇且不能阻塞的循環(huán)來等待處理這些 "突發(fā)" 事件. 于是, 基于 事件循環(huán)機(jī)制 的 單線程模型 就出現(xiàn)了。

Dart的事件循環(huán)機(jī)制由一個(gè)消息循環(huán)(Event Looper)和兩個(gè)消息隊(duì)列構(gòu)成蛹磺。兩個(gè)消息隊(duì)列分別是事件隊(duì)列(Event Queue)和微任務(wù)隊(duì)列(Microtask Queue)同仆。

1.Event Looper

Dart在執(zhí)行完main函數(shù)后, Event Looper就開始工作, Event Looper優(yōu)先全部執(zhí)行完 Microtask Queue中的event, 直到Microtask Queue為空時(shí), 才會(huì)執(zhí)行Event Looper中的 event, Event Looper為空時(shí)才可以退出循環(huán)俗批。

2.Event Queue
  • Event Queue的 event 來源于外部事件或Future
  • 外部事件:例如輸入/輸出, 手勢(shì), 繪制, 計(jì)時(shí)器, Stream等蕴侣,
  • Future:用于自定義Event Queue事件臭觉。

對(duì)于外部事件, 一旦沒有任何 microtask 要執(zhí)行, Event loop 才會(huì)考慮 event queue 中的第一項(xiàng), 并且將會(huì)執(zhí)行它。

  • 案例:向Event Queue中添加事件任務(wù)
Future(() {
  // 事件任務(wù)
});
3.Microtask Queue
  • Microtask Queue的優(yōu)先級(jí)高于Event Queue.
  • 使用場(chǎng)景: 想要在稍后完成一些任務(wù)(microtask) 但又希望在執(zhí)行下一個(gè)事件(event)之前執(zhí)行.

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 次.

  • 案例:向 Microtask Queue 添加微任務(wù):
scheduleMicrotask(() {
  // 微任務(wù)
});

二狞膘、Future

1. Future 實(shí)例有 3 個(gè)常用方法:
  • then((value){...}): 正常運(yùn)行時(shí)執(zhí)行
  • catchError((err){...}): 出現(xiàn)錯(cuò)誤時(shí)執(zhí)行
  • whenComplete((){...}): 不管成功與否都會(huì)執(zhí)行
2.鏈?zhǔn)秸{(diào)用

Future 可以在 then()方法中返回另一個(gè) Future 實(shí)例, 從而達(dá)到鏈?zhǔn)秸{(diào)用的效果, 這對(duì)那些有數(shù)據(jù)關(guān)聯(lián)的網(wǎng)絡(luò)請(qǐng)求很有用

3.其他

Future 除了默認(rèn)構(gòu)造器外, 還提供了幾個(gè)常用的命名構(gòu)造器:

  • Future.value(): 創(chuàng)建一個(gè)返回具體數(shù)據(jù)的 Future 實(shí)例
  • Future.error(): 創(chuàng)建一個(gè)返回錯(cuò)誤的 Future 實(shí)例
  • Future.delayed(): 創(chuàng)建一個(gè)延時(shí)執(zhí)行的 Future 實(shí)例

三什乙、async/await

1、基本使用

  • await 必須在 async 函數(shù)中使用
  • async 函數(shù)返回的結(jié)果必須是一個(gè) Future

四辅愿、isolate

所有的 Dart 代碼都是在 isolate 中運(yùn)行的, 它就是機(jī)器上的一個(gè)小空間, 具有自己的私有內(nèi)存塊和一個(gè)運(yùn)行著 Event Looper 的單個(gè)線程. 每個(gè) isolate 都是相互隔離的, 并不像線程那樣可以共享內(nèi)存. 一般情況下, 一個(gè) Dart 應(yīng)用只會(huì)在一個(gè) isolate 中運(yùn)行所有代碼, 但如果有特殊需要, 可以開啟多個(gè):

1忆某、創(chuàng)建 isolate (Dart API)

Dart 默認(rèn)提供了 Isolate.spawn(entryPoint, message) 用于開啟 isolate, 通過源碼可以知道形參 message 其實(shí)是 形參 entryPoint 對(duì)應(yīng)的函數(shù)執(zhí)行時(shí)需要的參數(shù)弃舒。
使用 Isolate.spawn(entryPoint, message) 開啟 isolate, 并指定要執(zhí)行的任務(wù):

import 'dart:isolate';
main(List<String> args) {
  print("main start");
  Isolate.spawn(calc, 100);
  print("main end");
}

void calc(int count) {
  var total = 0;
  for (var i = 0; i < count; i++) {
    total += i;
  }
  print(total);
}
2状原、isolate 通信 (單向)

isolate 間可以一起工作的唯一方法是通過來回傳遞消息. 一般情況下, 子isolate 會(huì)將運(yùn)行結(jié)果通過管道以消息的形式發(fā)送到 主isolate, 并在 主isolate 的 Event Looper 中處理該消息, 這時(shí)就需要借助 ReceivePort 來處理消息的傳遞了:

  • 在啟動(dòng) 子isolate 時(shí), 將 主isolate 的發(fā)送管道(SendPort)作為參數(shù)傳遞給 子isolate.
  • 子isolate 在執(zhí)行完畢時(shí), 可以利用管道(SendPort)給 主isolate 發(fā)送信息.
import 'dart:isolate';
main(List<String> args) async {
  print("main start");

  // 1. 創(chuàng)建管道
  var receivePort = ReceivePort();

  // 2. 創(chuàng)建isolate
  Isolate isolate = await Isolate.spawn(foo, receivePort.sendPort);

  // 3. 監(jiān)聽管道
  receivePort.listen((message) {
    print(message);
    // 不再使用時(shí), 關(guān)閉管道
    receivePort.close();
    // 不再使用時(shí), 將 isolate 殺死
    isolate.kill();
  });

  print("main end");
}

void foo(SendPort sendPort) {
  sendPort.send("Hello lqr");
}
3苗踪、創(chuàng)建 isolate (Flutter API)

Flutter 提供了更為方便的開啟 isolate 的 API: compute() 函數(shù). 以下是示例代碼:

main(List<String> args) async {
  int result = await compute(powerNum, 5);
  print(result);
}

int powerNum(int num) {
  return num * num;
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末通铲,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子央串,更是在濱河造成了極大的恐慌碗啄,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,324評(píng)論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件饲宿,死亡現(xiàn)場(chǎng)離奇詭異胆描,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)国夜,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,356評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門短绸,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人醋闭,你說我怎么就攤上這事证逻。” “怎么了囚企?”我有些...
    開封第一講書人閱讀 162,328評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵洞拨,是天一觀的道長负拟。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么秸歧? 我笑而不...
    開封第一講書人閱讀 58,147評(píng)論 1 292
  • 正文 為了忘掉前任衅澈,我火速辦了婚禮,結(jié)果婚禮上经备,老公的妹妹穿的比我還像新娘部默。我一直安慰自己,他們只是感情好傅蹂,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,160評(píng)論 6 388
  • 文/花漫 我一把揭開白布份蝴。 她就那樣靜靜地躺著,像睡著了一般婚夫。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上镐躲,一...
    開封第一講書人閱讀 51,115評(píng)論 1 296
  • 那天侍筛,我揣著相機(jī)與錄音,去河邊找鬼裆熙。 笑死禽笑,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的佳镜。 我是一名探鬼主播,決...
    沈念sama閱讀 40,025評(píng)論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼蚀同,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了衰猛?” 一聲冷哼從身側(cè)響起刹孔,我...
    開封第一講書人閱讀 38,867評(píng)論 0 274
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎卦睹,沒想到半個(gè)月后方库,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,307評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡笼痹,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,528評(píng)論 2 332
  • 正文 我和宋清朗相戀三年酪穿,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片救赐。...
    茶點(diǎn)故事閱讀 39,688評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡只磷,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出预厌,到底是詐尸還是另有隱情元媚,我是刑警寧澤,帶...
    沈念sama閱讀 35,409評(píng)論 5 343
  • 正文 年R本政府宣布刊棕,位于F島的核電站,受9級(jí)特大地震影響网严,放射性物質(zhì)發(fā)生泄漏嗤无。R本人自食惡果不足惜怜庸,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,001評(píng)論 3 325
  • 文/蒙蒙 一驴一、第九天 我趴在偏房一處隱蔽的房頂上張望灶壶。 院中可真熱鬧,春花似錦驰凛、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,657評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至井联,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間烙常,已是汗流浹背鹤盒。 一陣腳步聲響...
    開封第一講書人閱讀 32,811評(píng)論 1 268
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留驼鞭,地道東北人尺碰。 一個(gè)月前我還...
    沈念sama閱讀 47,685評(píng)論 2 368
  • 正文 我出身青樓,卻偏偏與公主長得像穴张,于是被迫代替她去往敵國和親两曼。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,573評(píng)論 2 353

推薦閱讀更多精彩內(nèi)容