接觸過Flutter的人都知道,Flutter是用Dart來寫的,Dart沒有進程和線程的概念,全部的Dart代碼都是在isolate上運行的,那麼isolate究竟是什麼?本系列的文章將詳細討論。這篇文章討論事件隊列(event loop)及Dart代碼運行順序。web
咱們對Dart代碼進行分類:同步代碼和異步代碼; 咱們在寫Dart代碼的時候,就只有兩種代碼,bash
這兩類代碼是不一樣的:架構
同步代碼和異步代碼運行的順序是不一樣的:app
先運行同步代碼,在運行異步代碼
複製代碼
就是,即便我異步代碼寫在最前面,同步代碼寫在最後面,很差意思,我也是先運行後面的同步代碼,同步代碼都運行完後,在運行前面的異步代碼。異步
異步代碼是運行在event loop
裏的,這是一個很重要的概念,這裏能夠理解成Android裏的Looper機制,是一個死循環,event loop
不斷的從事件隊列裏取事件而後運行。async
下面是event loop大體的運行圖: oop
這個很好理解,事件events加到Event queue裏,Event loop循環從Event queue裏取Event執行。這個理解後,在看event loop詳細的運行圖: ui
從這裏看到,啓動app(start app)後:spa
這裏多了兩個名詞:MicroTask
和Event
,這表明了兩個不一樣的異步task線程
並且能夠看出:
MicroTask
這個你們應該不太清楚,可是這個也是dart:async
提供的異步方法,使用方式:
// Adds a task to the 先查看MicroTask queue.
scheduleMicrotask((){
// ...code goes here...
});
複製代碼
或者:
new Future.microtask((){
// ...code goes here...
});
複製代碼
Event咱們就很清楚了,就是Future修飾的異步方法,使用方式:
// Adds a task to the Event queue.
new Future(() {
// ...code goes here...
});
複製代碼
純粹講理論知識不太好理解,咱們直接上代碼,講一個例子,看以下的代碼,請問打印順序是什麼樣的?
import 'dart:async';
void main() {
print('main #1 of 2');
scheduleMicrotask(() => print('microtask #1 of 3'));
new Future.delayed(new Duration(seconds:1),
() => print('future #1 (delayed)'));
new Future(() => print('future #2 of 4'))
.then((_) => print('future #2a'))
.then((_) {
print('future #2b');
scheduleMicrotask(() => print('microtask #0 (from future #2b)'));
})
.then((_) => print('future #2c'));
scheduleMicrotask(() => print('microtask #2 of 3'));
new Future(() => print('future #3 of 4'))
.then((_) => new Future(
() => print('future #3a (a new future)')))
.then((_) => print('future #3b'));
new Future(() => print('future #4 of 4'))
.then((_){
new Future(() => print('future #4a'));
})
.then((_) => print('future #4b'));
scheduleMicrotask(() => print('microtask #3 of 3'));
print('main #2 of 2');
}
複製代碼
首先運行同步代碼
因此是:
main #1 of 2
main #2 of 2
複製代碼
接下來是異步代碼
Dart的Event Loop是先判斷 microtask queue
裏有沒有task,有的話運行microtask
,microtask
運行完後,在運行event queue
裏的event task
,一個event task
運行完後,再去運行 microtask queue
,而後在運行event queue
。
microtask queue
這裏就是:
microtask #1 of 3
microtask #2 of 3
複製代碼
event queue event queue還有有特殊的狀況須要考慮:
Future.delayed
須要延遲執行的,Dart是怎麼執行的呢,是在延遲時間到了以後纔將此task加到event queue
的隊尾,因此萬一前面有很耗時的任務,那麼你的延遲task不必定能準時運行
Future.then
Future.then裏的task是不會加入到event queue
裏的,而是當前面的Future執行完後當即掉起,因此你若是想保證異步task的執行順序必定要用then,不然Dart不保證task的執行順序
scheduleMicrotask
一個event task
運行完後,會先去查看Micro queue
裏有沒有能夠執行的micro task
。沒有的話,在執行下一個event task
這裏就是:
```
future #2 of 4
future #2a
future #2b
future #2c
microtask #0 (from future #2b)
future #3 of 4
future #4 of 4
future #4b
future #3a (a new future)
future #3b
future #4a
future #1 (delayed)
```
複製代碼
這裏你確定好奇爲啥future #3 of 4
後面是future #4 of 4
,而不是future #3a (a new future)
,由於 future #3 of 4
的then裏又新建了一個Future:future #3a (a new future)
,因此future #3a (a new future)
這個task會加到event queue
的最後面。
最後的結果就是:
main #1 of 2
main #2 of 2
microtask #1 of 3
microtask #2 of 3
microtask #3 of 3
future #2 of 4
future #2a
future #2b
future #2c
microtask #0 (from future #2b)
future #3 of 4
future #4 of 4
future #4b
future #3a (a new future)
future #3b
future #4a
future #1 (delayed)
複製代碼