一.使用Future异步编程
1.基本的异步代码示例
aboutFuture() {
print('外部代码1');
Future(() {
print('执行任务A');
// throw Exception('error');
return '任务A';
}).then((value) => print('$value完成'))
.whenComplete(() => print('异步完成'))
.timeout(Duration(seconds: 1))
.catchError((e) {
print(e);
});
print('外部代码2');
// flutter: 外部代码1
// flutter: 外部代码2
// flutter: 执行任务A
// flutter: 任务A完成
// flutter: 异步完成
}
- 任务代码块,执行的异步任务
-
throw Exception('')
,抛出异常
-
return
,返回数据,then代码块回调参数值value
-
then
, 处理future返回值的代码块。then本质就是将里面的代码丢到微任务队列去执行,因此事件执行完会优先执行.then
-
whenComplete
,当任务代码块及.then执行完成时回调
-
timeout
,异步任务设置的超时时间
-
catchError
,捕获异常的回调
注意:一般将catchError写在链的最后面,catchError返回值为Future
,其他方法返回Future
,如果先写了catchError
,后续如果抛异常程序就会报错,因此一般写在链的最后面
2.async和await
aboutAwaitAndAsync() async {
print('外部代码1');
await Future((){
//耗时操作
//1.后面的操作必须是异步的才能使用await修饰
//2.当前这个函数也必须是async修饰的
for (int i = 0 ; i < 10000000000; i ++) {}
return '遍历完毕';
}).then((value) => print(value));
print('外部代码2');
// flutter: 外部代码1
// flutter: 遍历完毕
// flutter: 外部代码2
}
3.多个异步任务
//1.初识Future,多个任务按事件队列顺序执行
testFuture() {
print('外部代码1');
Future(() {
return '任务1';
}).then((value) => print(value));
Future(() {
sleep(Duration(seconds: 2));
return '任务2';
}).then((value) => print(value));
Future(() {
return '任务3';
}).then((value) => print(value));
Future(() {
return '任务4';
}).then((value) => print(value));
print('外部代码2');
// flutter: 外部代码1
// flutter: 外部代码2
// flutter: 任务1
// flutter: 任务2
// flutter: 任务3
// flutter: 任务4
}
4.多个任务执行完后,再执行某个任务
//2.wait,当所有任务执行完成后,会执行then
testFuture2() {
Future.wait([Future(() {
return '任务1';
}), Future(() {
return '任务2';
}),Future(() {
return '任务3';
})]).then((value) => print(value[0] + value[1] + value[2]));
}
5.Future.value
futureValue() async {
int a = await Future.value(1);
print(a); //1
}
6.Future.delayed
futureDeley() {
print('外部代码1');
Future.delayed(Duration(seconds: 2), () {
print('开始任务');
});
print('外部代码2');
// flutter: 外部代码1
// flutter: 外部代码2
// flutter: 开始任务
}
7.Future.error
futureError() {
Future.error('Test Error').catchError((e)=>print(e)); //Test Error
}
8.Future.error与.then中的onError
-
Future.catchError
,一般用于获取原始Future抛出的Error(包含Future代码块里抛出的异常),不能处理回调函数抛出的Error(比如then、catchError)
-
onError
,只能处理当前Future的错误
futureError() {
Future.error('Test Error').then((value) {
throw '.then error';
}).catchError((e) {
print(e); //Test Error
throw '.then error2';
}).then(print, onError: (e)=>print(e));// .then error2
}
9.Flutter.timeout
futureTimeout() {
Future.delayed(Duration(seconds: 2)).timeout(Duration(seconds: 1)).catchError(print);
}
10.Future.foreach
futureForeach() {
Future.forEach({1,2,3}, (num) {
return Future.delayed(Duration(seconds: num as int), () {
print("第$num秒执行");
});
});
// flutter: 第1秒执行
// flutter: 第2秒执行
// flutter: 第3秒执行
}
11.Future.any
- 返回第一个执行完成的Future,无论结果是正确的还是异常
futureAny() {
Future.any([1,2,3].map((e) => Future.delayed(Duration(seconds: e), ()=>e))).then(print).catchError(print); //1
}
12.Future.doWhile
- 重复的执行某个动作,直到返回false/true
- true - 执行循环,false - 退出循环
futureDoWhile() {
Future.doWhile(() {
int num = Random().nextInt(20);
print(num);
if (num == 5) {
print('doWhile结束');
return false;
}else {
return true;
}
});
}
13.Future.sync
- 添加同步任务时,会阻塞当前线程,sync执行完成后,才能执行下一行代码
futureSync() {
Future(()=>print('任务1'));
Future.sync(()=>print('任务2'));
Future(()=>print('任务3'));
Future.microtask(() => print('任务4'));
// flutter: 任务2
// flutter: futureSync
// flutter: 任务4
// flutter: 任务1
// flutter: 任务3
}
futureSync();
print('futureSync');
Future.microtask
- 创建一个在
microtask queue
运行的Future,microtask queue
优先级>event queue。因此位于micro queue上的Future会优先于其它Future。相当于添加了一个微任务
14.微任务(Micro Task)
- 表示一个短时间内就会完成的异步任务,它的优先级最高
//3.初识微任务,微任务优先级高
testFuture3() {
print('外部代码1');
Future(()=>print('A')).then((value) => print('A结束'));
Future(()=>print('B')).then((value) => print('B结束'));
scheduleMicrotask(() {
print('微任务A');
});
print('外部代码2');
// flutter: 外部代码1
// flutter: 外部代码2
// flutter: 微任务A
// flutter: A
// flutter: A结束
// flutter: B
// flutter: B结束
}
15.关于微任务与事件任务优先级的一些练习
//7.微任务与事件任务执行顺序练习
testFuture7() {
Future x1 = Future(()=>null);
Future x = Future(()=>print('1'));
Future(() {
print('2');
scheduleMicrotask(()=>print('13'));
x1.then((value){
print('6');
scheduleMicrotask(()=>print('7'));
}).then((value) => print('8'));
});
scheduleMicrotask(()=>print('3'));
x.then((value) => print('4'));
Future(() {
print('9');
Future(()=>print('10'));
}).then((value) => print('11'));
Future(()=>print('12'));
print('5');
//5、3、1、4、2、13、6、8、7、9、11、12、10
}
//6.微任务与事件任务执行顺序练习
testFuture6() {
Future x1 = Future(()=>null);
Future x = Future(()=>print('1'));
Future(() {
print('2');
x1.then((value){
print('6');
scheduleMicrotask(()=>print('7'));
}).then((value) => print('8'));
});
scheduleMicrotask(()=>print('3'));
x.then((value) => print('4'));
print('5');
//53142687
}
//5.微任务与事件任务执行顺序练习
testFuture5() {
Future x1 = Future(()=>null);
Future x = Future(()=>print('1'));
Future(()=>print('2'));
scheduleMicrotask(()=>print('3'));
x.then((value) => print('4'));
print('5');
x1.then((value){
print('6');
scheduleMicrotask(()=>print('7'));
}).then((value) => print('8'));
//53687142
}
//4.微任务与事件任务执行顺序练习
testFuture4() {
Future x = Future(()=>print('1'));
Future(()=>print('2'));
scheduleMicrotask(()=>print('3'));
x.then((value) => print('4'));
print('5');
//53142
}
二.Event Loop(事件循环)
- 每一次事件循环中,Dart总是先去第一个microtask queue中查询是否有可执行的任务,如果没有,才会处理后续的event queue
- 事件队列(event queue),包含所有的外来事件:
I/O
、mouse events
、drawing events
、timers
、isalate之间的信息传递
- 微任务队列(microtask queue),表示一个短时间内就会完成的异步任务,它的优先级最高。只要队列中还有任务,就可以一直霸占着事件循环。microtask queue添加的任务主要是由 Dart内部产生
注意:如果有太多的微任务,可能会霸占着事件循环,导致event queue中的触摸、绘制等外部事件造成阻塞卡顿