代码
import 'package:dio/dio.dart';
//使用async和await做异步调用.
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,访问数据库或网络,拿到数据, 返回给界面.
如果异步操作, 界面可能会在A拿到数据之前就初始化完成,这时界面收到的就是null.
这个场景只能用同步,保证A拿到数据之后,界面才初始化.(或者异步,A拿到值后,使界面重新刷新,这会影响用户体验)
async
与await
: 将异步方法按同步方法操作
-
async
描述一个执行异步操作的方法 -
await
表示一直等待异步方法返回结果,才继续往后执行
Future<String> method5() async {
return "5";
}
void testD() async {
print(1);
String f5 = await method5();
print(f5);
print(3);
}
结果:
1
5
3
场景2
用户做完一个题目,点击下一题,需要将用户做题结果存到数据库,但是这可以异步操作, 使用户点击下一题时马上显示下一题的界面,不需要用户等待上一题结果存数据库的时间.
当遇到有需要延迟的运算(async)时,将其放入到延迟运算的队列(await)中去,把不需要延迟运算的部分先执行掉,最后再来处理延迟运算的部分。
代码示例:
import 'package:dio/dio.dart';
/* 这个示例是, 在main函数里, 用getData请求网络API, 同时异步打印一句话.
可以看到在getData请求网络api完成之前, 这句话已经打印完成了 */
void main() {
getData().then((result) {
print("接口返回的数据是:${result}");
}).whenComplete((){
print("异步任务处理完成");
}).catchError((){
print("出现异常了");
});
print("我是在请求数据后面的代码呦!"); //异步打印出来
}
/**
* 请求接口获取数据
*/
Future<Response> getData() async {
String url = "http://v.juhe.cn/toutiao/index";
String key = "4c52313fc9247e5b4176aed5ddd56ad7";
String type = "keji";
print("开始请求数据↓↓↓↓↓↓↓↓↓↓↓↓");
Response response =
await Dio().get(url, queryParameters: {"type": type, "key": key});
print("请求完成↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑");
return response;
}
结果:
开始请求数据↓↓↓↓↓↓↓↓↓↓↓↓
我是在请求数据后面的代码呦!
请求完成↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑
接口返回的数据是:{"reason":"成功的返回","result":{"stat":"1","data":[{"uniquekey":"348c7f269f45c447bee1cb7be4098529","title":"Vivid Audio Giya G1S,魔人布欧和他的新装","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}
异步任务处理完成
场景3
在数据库里根据 id 查询名字:
Future queryName(int id) {
// 创建一个completer
var completer = new Completer();
// 查询数据库,然后根据成功或者失败执行相应的callback回调,这个过程是异步的
database.query("select name from user where id = $id", (results) {
completer.complete(results);
}, (error) {
completer.completeError(error);
});
// return 在query结果出来之前就会被执行
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.");
});
}