異步是所有開發(fā)語言中非常重要的一環(huán)冈止,在執(zhí)行耗時(shí)操作的時(shí)候不會(huì)讓主線程長時(shí)間無響應(yīng)狂票,這一點(diǎn)在移動(dòng)端開發(fā)中尤其重要
Dart庫中包含許多返回Future或Stream對(duì)象的函數(shù)。
這些函數(shù)是異步的:它們?cè)谠O(shè)置可能耗時(shí)的操作(例如I / O)后返回熙暴,而不等待該操作完成闺属。
Futures
async和await關(guān)鍵字支持異步編程慌盯,允許您編寫看起來類似于同步代碼的異步代碼。
await關(guān)鍵字在Dart2中才加入其中
使用異步的方法有兩個(gè)掂器,第一個(gè)是使用await 另外一個(gè)是使用Future Api
使用async和await的代碼是異步的亚皂,但它看起來很像同步代碼。
例如国瓮,這里有一些代碼使用await來等待異步函數(shù)的結(jié)果:
await lookUpVersion();
要使用await關(guān)鍵字灭必,需要在async包裹的代碼塊方法中使用
Future checkVersion() async {
var version = await lookUpVersion();
// Do something with version
}
注意:雖然異步函數(shù)可能執(zhí)行耗時(shí)的操作,但它不會(huì)等待這些操作乃摹。
相反禁漓,異步函數(shù)只在遇到第一個(gè)await表達(dá)式(詳細(xì)信息)時(shí)才會(huì)執(zhí)行。
然后它返回一個(gè)Future對(duì)象孵睬,僅在await表達(dá)式完成后才恢復(fù)執(zhí)行播歼。
你也可以針對(duì)await進(jìn)行一個(gè)try catch 防止出現(xiàn)異常
try {
version = await lookUpVersion();
} catch (e) {
// React to inability to look up the version
}
你也可以多次使用await來執(zhí)行多次耗時(shí)操作
var entrypoint = await findEntrypoint();
var exitCode = await runExecutable(entrypoint, args);
await flushThenExit(exitCode);
以 async 關(guān)鍵字聲明的方法必須返回一個(gè)Future的對(duì)象,如果你需要返回一個(gè)有用的值掰读,請(qǐng)將該對(duì)象加入到泛型里面
Future<String> lookUpVersion() async => '1.0.0';
Steam Api
當(dāng)您需要從Stream獲取值時(shí)秘狞,您有兩個(gè)選擇:使用async和異步for循環(huán)(等待)
或者使用Stream API箱沦,如庫瀏覽中所述殿漠。
注意:在使用await for前,請(qǐng)確保它使代碼更清晰驯击,并且您確實(shí)希望等待所有流的結(jié)果雾狈。
例如廓潜,您通常不應(yīng)該使用await for UI事件偵聽器,因?yàn)閁I框架會(huì)發(fā)送無窮無盡的事件流善榛。
異步for循環(huán)具有以下形式:
await for (varOrType identifier in expression) {
// Executes each time the stream emits a value. 這個(gè)expression需要是一個(gè)事件流列表
}
表達(dá)式的值必須具有Stream類型。
執(zhí)行過程如下:
1.等到流發(fā)出一個(gè)值呻畸。
2.執(zhí)行for循環(huán)的主體移盆,將變量設(shè)置為該發(fā)出的值。
3.重復(fù)1和2伤为,直到關(guān)閉流咒循。
要停止偵聽流,可以使用break或return語句绞愚,該語句會(huì)從for循環(huán)中斷開并從流中取消取消叙甸。
生成器
當(dāng)您需要懶加載一個(gè)序列的值時(shí),請(qǐng)考慮使用生成器函數(shù)位衩。Dart內(nèi)置支持兩種生成器功能:同步和異步
要實(shí)現(xiàn)同步生成器函數(shù)裆蒸,請(qǐng)將函數(shù)體標(biāo)記為sync *,并使用yield語句來傳遞值:
Iterable<int> naturalsTo(int n) sync* {
int k = 0;
while (k < n) yield k++;
}
異步的寫法很類似糖驴,區(qū)別就在于關(guān)鍵字
Stream<int> asynchronousNaturalsTo(int n) async* {
int k = 0;
while (k < n) yield k++;
}
如果您的生成器是遞歸的僚祷,則可以使用yield *來提高其性能:
Iterable<int> naturalsDownFrom(int n) sync* {
if (n > 0) {
yield n;
yield* naturalsDownFrom(n - 1);
}
}
可調(diào)用的類
如果你想你的類可以像方法一樣去調(diào)用的話佛致,你需要在類里面增加一個(gè)call方法