代碼
import 'package:dio/dio.dart';
//使用async和await做異步調(diào)用.
void getHttp() async {
try {
Response response = await Dio().get("https://www.baidu.com");
print(response);
print("------------");
print(response.data.toString());
} catch(e){
print(e);
}
}
void main() {
// getHttp();
//單個異步事件
Future.delayed(new Duration(seconds:2),(){
return 'hi world!';
}).then((data){
print(data);
} );
//多個異步事件
Future.wait([
Future.delayed(new Duration(seconds: 2),(){
return "hello";
}),
Future.delayed(new Duration(seconds: 4),(){
return "world!";
})
]).then((results){
print(results[0]+results[1]);
}).catchError((e){
print(e);
});
}
場景1
界面初始化時,某個變量A,訪問數(shù)據(jù)庫或網(wǎng)絡(luò),拿到數(shù)據(jù), 返回給界面.
如果異步操作, 界面可能會在A拿到數(shù)據(jù)之前就初始化完成,這時界面收到的就是null.
這個場景只能用同步,保證A拿到數(shù)據(jù)之后,界面才初始化.(或者異步,A拿到值后,使界面重新刷新,這會影響用戶體驗(yàn))
async 與await : 將異步方法按同步方法操作
-
async描述一個執(zhí)行異步操作的方法 -
await表示一直等待異步方法返回結(jié)果,才繼續(xù)往后執(zhí)行
Future<String> method5() async {
return "5";
}
void testD() async {
print(1);
String f5 = await method5();
print(f5);
print(3);
}
結(jié)果:
1
5
3
場景2
用戶做完一個題目,點(diǎn)擊下一題,需要將用戶做題結(jié)果存到數(shù)據(jù)庫,但是這可以異步操作, 使用戶點(diǎn)擊下一題時馬上顯示下一題的界面,不需要用戶等待上一題結(jié)果存數(shù)據(jù)庫的時間.
當(dāng)遇到有需要延遲的運(yùn)算(async)時,將其放入到延遲運(yùn)算的隊(duì)列(await)中去,把不需要延遲運(yùn)算的部分先執(zhí)行掉,最后再來處理延遲運(yùn)算的部分。
代碼示例:
import 'package:dio/dio.dart';
/* 這個示例是, 在main函數(shù)里, 用getData請求網(wǎng)絡(luò)API, 同時異步打印一句話.
可以看到在getData請求網(wǎng)絡(luò)api完成之前, 這句話已經(jīng)打印完成了 */
void main() {
getData().then((result) {
print("接口返回的數(shù)據(jù)是:${result}");
}).whenComplete((){
print("異步任務(wù)處理完成");
}).catchError((){
print("出現(xiàn)異常了");
});
print("我是在請求數(shù)據(jù)后面的代碼呦!"); //異步打印出來
}
/**
* 請求接口獲取數(shù)據(jù)
*/
Future<Response> getData() async {
String url = "http://v.juhe.cn/toutiao/index";
String key = "4c52313fc9247e5b4176aed5ddd56ad7";
String type = "keji";
print("開始請求數(shù)據(jù)↓↓↓↓↓↓↓↓↓↓↓↓");
Response response =
await Dio().get(url, queryParameters: {"type": type, "key": key});
print("請求完成↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑");
return response;
}
結(jié)果:
開始請求數(shù)據(jù)↓↓↓↓↓↓↓↓↓↓↓↓
我是在請求數(shù)據(jù)后面的代碼呦!
請求完成↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑
接口返回的數(shù)據(jù)是:{"reason":"成功的返回","result":{"stat":"1","data":[{"uniquekey":"348c7f269f45c447bee1cb7be4098529","title":"Vivid Audio Giya G1S,魔人布?xì)W和他的新裝","date":"2020-03-18 14:20","category":"科技","author_name":"家電論壇","url":"https://v.juhe.cn/toutiao/s?id=https%3A%2F%2Fmini.eastday.com%2Fmobile%2F200318142004727.html","thumbnail_pic_s":"https://08imgmini.eastday.com/mobile/20200318/20200318142004_c09487f56a73d96ba7c2bcc60193ed2e_7_mwpm_03200403.jpg","thumbnail_pic_s02":"http://08imgmini.eastday.com/mobile/20200318/20200318142004_c09487f56a73d96ba7c2bcc60193ed2e_6_mwpm_03200403.jpg","thumbnail_pic_s03":"http://08imgmini.eastday.com/mobile/20200318/20200318142004_c09487f56a73d96ba7c2bcc60193ed2e_3_mwpm_03200403.jpg"}]},"error_code":0}
異步任務(wù)處理完成
場景3
在數(shù)據(jù)庫里根據(jù) id 查詢名字:
Future queryName(int id) {
// 創(chuàng)建一個completer
var completer = new Completer();
// 查詢數(shù)據(jù)庫,然后根據(jù)成功或者失敗執(zhí)行相應(yīng)的callback回調(diào),這個過程是異步的
database.query("select name from user where id = $id", (results) {
completer.complete(results);
}, (error) {
completer.completeError(error);
});
// return 在query結(jié)果出來之前就會被執(zhí)行
return completer.future;
}
如何使用 queryName 呢?常見兩種方式來"打開箱子":await 或者 then。
await:
void runFuturesDemo2() async {
try {
final name = await queryName(100);
print("id 100 user name is $name");
} catch (e) {
print(e.toString());
} finally {
print("finally finished.");
}
}
then:
void runFuturesDemo2() {
queryName(100).then((name) {
print("id 100 user name is $name");
}, onError: (e) {
print(e.toString());
}).whenComplete(() {
print("finally finished.");
});
}