Flutter默认是单线程任务处理的,如果不开启新的线程,任务默认在主线程中处理。
Dart的事件循环(event loop)
- 事件队列 (
event queue)- 包含所有的外来事件:
I/O、mouse events、drawing events、timers、isolate之间的信息传递
- 包含所有的外来事件:
- 微任务队列 (
microtask queue)- 短时间内完成一个异步任务。优先级比
event queue要高,只要队列中还有任务,就可以一直霸占着时间循环。microtask queue添加的任务主要是由Dart内部产生。
- 短时间内完成一个异步任务。优先级比
因为
microtask queue的优先级高于event queue,所以如果microtask queue有太多的微任务, 那么就可能会霸占住当前的event loop。从而对event queue中的触摸、绘制等外部事件造成阻塞卡顿。
可以看到,在每一次事件循环中,Dart总是先去微任务队列microtask queue中查询是否有可执行的任务,如果没有,才会处理事件队列event queue的流程。
void test(){
Future((){
print('Future异步任务1');
});
sleep(Duration(seconds: 3));
scheduleMicrotask((){
print('微任务');
});
Future((){
print('Future异步任务2');
});
}
打印结果为:
flutter: 微任务
flutter: Future异步任务1
flutter: Future异步任务2
可以看到上述代码,scheduleMicrotask执行是在Future之前。
void test(){
Future((){
print('Future异步任务1');
scheduleMicrotask((){
print('微任务');
});
})
.then((value) {
print('执行Future.then 1方法');
})
.then((value) {
print('执行Future.then 2方法');
})
.whenComplete(() {
print('执行Future.whenComplete 方法');
});
}
打印结果为:
flutter: Future异步任务1
flutter: 执行Future.then 1方法
flutter: 执行Future.then 2方法
flutter: 执行Future.whenComplete 方法
flutter: 微任务
flutter: Future异步任务3
如果在Future当中添加微任务队列,微任务队列是在整个Future执行完毕后才会执行微任务当中的代码。可以看到在同等级别下,scheduleMicrotask执行是在Future之前。
void test(){
Future x1 = Future((){
print('Future1异步任务');
scheduleMicrotask((){
print('Future - x1 内部微任务');
});
})
.then((value) {
print('执行Future1.then 方法');
});
Future x2 = Future((){
print('Future2异步任务');
})
.then((value) {
print('执行Future2.then 方法');
});
x1.then((value) {
print('结尾再次调用Future.then方法');
});
}
打印结果为
flutter: Future1异步任务
flutter: 执行Future1.then 方法
flutter: 结尾再次调用Future.then方法
flutter: Future - x1 内部微任务
flutter: Future2异步任务
flutter: 执行Future2.then 方法
根据上述代码可以看到,如果Future已经执行完毕了,我们再来获取到这个Future的引用,然后再继续调用then()方法。对于这种情况,Dart会将后续加入的then()方法体放入microtask queue,尽快执行,所以结尾再次调用Future.then方法在Future - x1 内部微任务之前,更是在Future2操作之前。
Future高级用法
Future.timeout
本来Future会在2s后完成,但是timeout声明的是1s后超时,所以1s后Future会抛出TimeoutException:
void testFuture() {
Future.delayed(Duration(seconds: 2), () {
return 1;
}).timeout(Duration(seconds:1)).then(print).catchError(print);
}
testFuture();
print("在testFuture()执行之后打印。");
打印结果为:
在testFuture()执行之后打印。
TimeoutException after 0:00:01.000000: Future not completed
Future.foreach
根据某个集合对象,创建一系列的Future。并且会按顺序执行这些Future。例如,根据{1,2,3}创建3个延迟对应秒数的Future。执行结果为1秒后打印1,再过2秒打印2,再过3秒打印3,总时间为6秒:
void testFuture() {
Future.forEach({1,2,3}, (int num){
return Future.delayed(Duration(seconds: num),(){print("第$num秒执行");});
});
}
testFuture();
print("在testFuture()执行之后打印。");
打印结果为:
在testFuture()执行之后打印。
第1秒执行
第2秒执行
第3秒执行
Future.wait
等待多个Future完成,并收集它们的结果。有两种情况:
- 所有
Future都有正常结果返回。则Future的返回结果是所有指定Future的结果的集合:
void testFuture() async {
var future1 = Future.delayed(Duration(seconds: 1), (){
print('Future1执行完毕');
return 'Future1执行完毕';
});
var future2 = Future.delayed(Duration(seconds: 2), (){
print('Future2执行完毕');
return 'Future2执行完毕';
});
var future3 = Future.delayed(Duration(seconds: 3),(){
print('Future3执行完毕');
return 'Future3执行完毕';
});
Future.wait({future1,future2,future3}).then((value){
print('最终执行 value = $value');
})
.catchError((e){
});
}
打印结果为:
flutter: Future1执行完毕
flutter: Future2执行完毕
flutter: Future3执行完毕
flutter: 最终执行 value = [Future1执行完毕, Future2执行完毕, Future3执行完毕]
- 其中一个或者几个
Future发生错误,产生了error。则Future的返回结果是第一个发生错误的Future的值:
void testFuture() async {
var future1 = Future.delayed(Duration(seconds: 1), (){
print('Future1开始执行');
return 'Future1执行完毕';
});
var future2 = Future.delayed(Duration(seconds: 2), (){
print('Future2开始执行');
throw 'Future2发生错误了';
return 'Future2执行完毕';
});
var future3 = Future.delayed(Duration(seconds: 3),(){
print('Future3开始执行');
return 'Future3执行完毕';
});
Future.wait({future1,future2,future3}).then((value){
print('最终执行 value = $value');
})
.catchError((e){
print('捕获到了错误 ${e.toString()}');
});
}
打印结果为:
flutter: Future1开始执行
flutter: Future2开始执行
flutter: Future3开始执行
flutter: 捕获到了错误 Future2发生错误了
Future.any
返回的是第一个执行完成的Future的结果,不会管这个结果是正确的还是error,如果数组中有多个then只会返回第一个执行的,剩下的Future还是会继续执行:
void testFuture() async {
var future1 = Future.delayed(Duration(seconds: 1), (){
print('Future1开始执行');
return 'Future1执行完毕';
});
var future2 = Future.delayed(Duration(seconds: 2), (){
print('Future2开始执行');
return 'Future2执行完毕';
});
var future3 = Future.delayed(Duration(seconds: 3),(){
print('Future3开始执行');
return 'Future3执行完毕';
});
Future.any({future1,future2,future3}).then((value){
print('最终执行 value = $value');
})
.catchError((e){
print('捕获到了错误 ${e.toString()}');
});
}
打印结果为:
flutter: Future1开始执行
flutter: 最终执行 value = Future1执行完毕
flutter: Future2开始执行
flutter: Future3开始执行
Future.sync
会同步执行其入参函数,然后调度到microtask queue来完成自己。也就是一个阻塞任务,会阻塞当前代码,sync的任务执行完了,代码才能走到下一行:
void main() {
testFuture111112();
print('end');
}
void testFuture111112() {
sleep(Duration(seconds: 3));
Future((){
print("Future event 1");
});
scheduleMicrotask((){
print('微任务');
});
Future.sync(() {
print("Future sync microtask event 2");
});
Future((){
print("Future event 3");
});
Future.microtask((){
print("microtask event");
});
}
打印结果为:
flutter: Future sync microtask event 2
flutter: end
flutter: 微任务
flutter: microtask event
flutter: Future event 1
flutter: Future event 3