前言
最近flutter可謂是炙手可熱啊,極大多數(shù)的移動(dòng)開(kāi)發(fā)者以及前端開(kāi)發(fā)人員都會(huì)利用空閑時(shí)間選擇去學(xué)習(xí)一下這個(gè)由Google一手打造的跨平臺(tái)的移動(dòng)UI框架。而本文要講的是關(guān)于在flutter中進(jìn)行異步操作的相關(guān)知識(shí)。
關(guān)于Future
1.眾所周知,flutter采用的是Dart語(yǔ)言。在我們?nèi)粘5囊苿?dòng)開(kāi)發(fā)中,總會(huì)遇到一些需要延時(shí)操作的場(chǎng)景,例如網(wǎng)絡(luò)請(qǐng)求,例如等待某個(gè)操作完成后再操作另一個(gè)事件。在Android中我們可以開(kāi)啟一個(gè)新的線程來(lái)進(jìn)行相關(guān)的操作,而現(xiàn)在Dart是一個(gè)單線程的語(yǔ)言。因此,這時(shí)我們不得不采取異步的方式來(lái)進(jìn)行類似的延時(shí)操作。
2.說(shuō)到flutter中的異步操作,就不得不說(shuō)到Future這個(gè)類。它的字面意思就是未來(lái)的意思,而在flutter中,它即表示在未來(lái)某一時(shí)間獲取想要的對(duì)象的一種方式。
場(chǎng)景描述
1.首先,我們舉個(gè)帶有耗時(shí)操作的場(chǎng)景實(shí)例。用龜兔賽跑舉例子,將事件分了四個(gè)步驟。
// 兔子和烏龜同時(shí)開(kāi)始起跑
String startRun() {
print("兔子和烏龜同時(shí)開(kāi)始起跑!");
return "兔子和烏龜同時(shí)開(kāi)始起跑";
}
// 兔子等待烏龜并開(kāi)始睡覺(jué)(此方法為耗時(shí)操作)
String tuziWaitWugui() {
print("兔子醒來(lái)后發(fā)現(xiàn)烏龜已經(jīng)到終點(diǎn)了");
return "兔子醒來(lái)后發(fā)現(xiàn)烏龜已經(jīng)到終點(diǎn)了";
}
// 烏龜超越兔子
String wuguiOverstepTuzi() {
print("烏龜趁著兔子睡覺(jué)而超越了兔子!");
return "烏龜趁著兔子睡覺(jué)而超越了兔子";
}
// 烏龜贏了比賽
String wuguiWinGame() {
print("烏龜率先到達(dá)了終點(diǎn)!");
return "烏龜率先到達(dá)了終點(diǎn)";
}
2.如上代碼所示,第二個(gè)兔子等待烏龜?shù)姆椒ㄊ且粋€(gè)耗時(shí)方法,因?yàn)樗X(jué)是一個(gè)過(guò)程。下面我們?cè)趂lutter中按順序執(zhí)行這四個(gè)方法。
void main() { // 此方法會(huì)在一個(gè)StatefulWidget組件的initState方法中調(diào)用(這里的基礎(chǔ)知識(shí)還請(qǐng)自行科普)
startRun();
tuziWaitWugui();
wuguiOverstepTuzi();
wuguiWinGame();
}
3.在控制臺(tái)我們會(huì)發(fā)現(xiàn)輸入的print信息如下:
兔子和烏龜同時(shí)開(kāi)始起跑!
兔子醒來(lái)后發(fā)現(xiàn)烏龜已經(jīng)到終點(diǎn)了!
烏龜趁著兔子睡覺(jué)而超越了兔子!
烏龜率先到達(dá)了終點(diǎn)!
我們會(huì)發(fā)現(xiàn),由于Dart是單線程語(yǔ)言,因此只有當(dāng)方法二執(zhí)行完才能執(zhí)行后面的方法。也就是說(shuō)只要兔子不醒,烏龜是無(wú)法超過(guò)兔子的,這顯然不符合事件的邏輯。這時(shí),我們來(lái)看一下Future的使用,它就是專門用來(lái)解決這種需要異步操作的問(wèn)題的。
Future使用
1.Future是基于觀察者模式的,它定義了未來(lái)將要發(fā)生的事情。它有兩種使用方式,首先我們通過(guò)它的構(gòu)造函數(shù)來(lái)創(chuàng)建它。
void main() {
Future<String> tuziWaitFuture = new Future(tuziWaitWugui); // 創(chuàng)建Future,并將耗時(shí)方法二傳給構(gòu)造函數(shù)
// 執(zhí)行事件
startRun();
tuziWaitFuture.then((str) { // 異步操作邏輯在這里
print(str);
}).whenComplete(() { // 異步完成時(shí)的回調(diào)
print("whenComplete");
}).catchError((error) { // 捕獲異常或者異步出錯(cuò)時(shí)的回調(diào)
print("catchError");
});
wuguiOverstepTuzi();
wuguiWinGame();
}
// 控制臺(tái)輸出信息如下:
兔子和烏龜同時(shí)開(kāi)始起跑!
烏龜趁著兔子睡覺(jué)而超越了兔子!
烏龜率先到達(dá)了終點(diǎn)!
兔子醒來(lái)后發(fā)現(xiàn)烏龜已經(jīng)到終點(diǎn)了!
whenComplete
現(xiàn)在看輸入結(jié)果完全符合事件邏輯了吧!這里我們通過(guò)使用構(gòu)造方法來(lái)new一個(gè)Future。在Future的構(gòu)造方法中我們可以直接傳入一個(gè)方法,并且方法的返回值類型需要和Future的泛型一致。然后,我們使用了Future的三個(gè)回調(diào)方法,其中then方法中的參數(shù)就是傳入的方法中的返回值。同時(shí)需要說(shuō)明的是,我們的異步操作的邏輯就可以寫在then回調(diào)中。其余兩個(gè)回調(diào)方法我在代碼中的注釋也寫的很清楚了。
2.通過(guò)構(gòu)造函數(shù)創(chuàng)建Future的方式已經(jīng)知道。現(xiàn)在我們聯(lián)想這樣一個(gè)場(chǎng)景,譬如網(wǎng)絡(luò)請(qǐng)求,我們需要等待一個(gè)方法執(zhí)行完返回我們所需的數(shù)據(jù)后才能繼續(xù)向下執(zhí)行。這時(shí),我們就需要用到async和await關(guān)鍵字了。
// 首先聲明一個(gè)方法,返回Future對(duì)象,模擬網(wǎng)絡(luò)請(qǐng)求延時(shí)了一秒
Future<String> getNewsData() {
return new Future.delayed(new Duration(milliseconds: 1000), () {
return "新聞數(shù)據(jù)已經(jīng)返回";
});
}
// 在之前的main()方法中調(diào)用該方法
void main() async {
String newsData = await getNewsData();
print(newsData);
print("數(shù)據(jù)回來(lái)之后我才打印");
}
// 執(zhí)行后,控制臺(tái)輸出信息
新聞數(shù)據(jù)已經(jīng)返回
數(shù)據(jù)回來(lái)之后我才打印
首先,我們用Future.delayed方式創(chuàng)建一個(gè)延時(shí)返回一個(gè)字符串的方法,該方法返回的是一個(gè)Future對(duì)象。然后,我們?cè)趍ain方法中調(diào)用此函數(shù),并且將返回值賦給newsData變量。此時(shí)如果我們直接用等號(hào)將變量和方法連接IDE會(huì)提示報(bào)錯(cuò),錯(cuò)誤提示為方法返回的是一個(gè)Future對(duì)象。這時(shí)我們就要在方法的調(diào)用前面加上一個(gè)await關(guān)鍵字,同時(shí)還要在main方法的后面添加async關(guān)鍵字。
至于為什么這樣,我只能說(shuō)說(shuō)我的個(gè)人理解。因?yàn)镕uture表示未來(lái)想要的某個(gè)對(duì)象,所以我們需要有一個(gè)東西來(lái)聲明需要等待這個(gè)未來(lái)的對(duì)象,因此便出現(xiàn)了await關(guān)鍵字來(lái)標(biāo)明要等待這個(gè)對(duì)象返回。而至于async關(guān)鍵字,因?yàn)間etNewsData是執(zhí)行一個(gè)異步操作,所以要在方法上標(biāo)明這個(gè)方法中會(huì)調(diào)用異步操作方法。同時(shí),要記住一點(diǎn)就是await必須放在有async 標(biāo)識(shí)的函數(shù)里,才能執(zhí)行。
結(jié)語(yǔ)
本人也是剛剛?cè)腴Tflutter的小菜鳥(niǎo),之前對(duì)flutter包括Dart語(yǔ)言都是一無(wú)所知的。所以,也是根據(jù)自己的理解并參考了一些文章來(lái)總結(jié)了關(guān)于Future的簡(jiǎn)單使用方式,如有不對(duì)的地方還望指出哈!