这是我参与11月更文挑战的第21天,活动详情查看:2021最后一次更文挑战。
- 我们之前学习了异步编程和dart中的多线程,接下来我们学习下
异步多线程的结合
。
1. 异步中的多线程
先看一个例子,在异步中添加子线程,之后打印结果,打印结果是同步还是异步呢?
void main() {
isoLoadDemo();
}
void isoLoadDemo(){
Future(()=>compute(funcIso,1)).then((value) => print('1结束'));
Future(()=>compute(funcIso,2)).then((value) => print('2结束'));
Future(()=>compute(funcIso,3)).then((value) => print('3结束'));
Future(()=>compute(funcIso,4)).then((value) => print('4结束'));
Future(()=>compute(funcIso,5)).then((value) => print('5结束'));
}
funcIso(int num){
}
复制代码
打印顺序为异步
说明这个.then
在子线程中执行了,我们修改下
void isoLoadDemo(){
Future((){
compute(funcIso,1);
}).then((value) => print('1结束'));
Future((){
compute(funcIso,2);
}).then((value) => print('2结束'));
Future((){
compute(funcIso,3);
}).then((value) => print('3结束'));
Future((){
compute(funcIso,4);
}).then((value) => print('4结束'));
Future((){
compute(funcIso,5);
}).then((value) => print('5结束'));
}
复制代码
这个时候打印结果为:
说明按照添加的顺序同步,这里是因为这里我们把箭头函数
改为了函数。
void isoLoadDemo(){
Future((){
return compute(funcIso,1);
}).then((value) => print('1结束'));
Future((){
return compute(funcIso,2);
}).then((value) => print('2结束'));
Future((){
return compute(funcIso,3);
}).then((value) => print('3结束'));
Future((){
return compute(funcIso,4);
}).then((value) => print('4结束'));
Future((){
return compute(funcIso,5);
}).then((value) => print('5结束'));
}
复制代码
我们添加了return
,打印结果又是异步的了
我们看下
compute
是什么
ComputeImpl
也是一个future
。
- 如果我们的异步返回的子线程的
Future
,那么我们.then
执行的是子线程future的then
。 - 如果我们不
return
,这个时候执行的是当前异步的.then
.
void isoLoadDemo(){
Future((){
print('1');
return compute(funcIso,1);
}).then((value) => print('1结束'));
Future((){
print('2');
return compute(funcIso,2);
}).then((value) => print('2结束'));
Future((){
print('3');
return compute(funcIso,3);
}).then((value) => print('3结束'));
Future((){
print('4');
return compute(funcIso,4);
}).then((value) => print('4结束'));
Future((){
print('5');
return compute(funcIso,5);
}).then((value) => print('5结束'));
}
复制代码
我们看下异步任务执行的顺序是有序的还是无序的,打印结果:
说明异步任务执行的顺序是根据我们
添加任务顺序
进行执行的,我们修改下
void isoLoadDemo(){
Future((){
print('1');
compute(funcIso,1);
}).then((value) => print('1结束'));
Future((){
print('2');
}).then((value) => print('2结束'));
Future((){
print('3');
compute(funcIso,3);
}).then((value) => print('3结束'));
Future((){
print('4');
compute(funcIso,4);
}).then((value) => print('4结束'));
Future((){
print('5');
compute(funcIso,5);
}).then((value) => print('5结束'));
}
复制代码
这个时候.then
打印结果是同步还是异步呢?打印结果:
因为我们没有
return 子线程的future
,因此当前的.then执行的当前异步任务的then
。
2. 异步任务中微任务
我们看个例子
void taskDemo(){
Future future = Future((){
print('异步任务1');
scheduleMicrotask((){
print('微任务1');
});
});
future.then((value) => print('微任务2'));
future.whenComplete(() => print('微任务3'));
}
复制代码
我们知道.then和.whenComplete
都是相当于微任务
,因此他是在当前异步任务执行完成就会执行。
我们修改下.then
和.whenComplete
的执行顺序,他们是按照添加的顺序
执行的。
void taskDemo(){
Future future = Future((){
print('异步任务1');
scheduleMicrotask((){
print('微任务1');
});
});
future.whenComplete(() => print('微任务3'));
future.then((value) => print('微任务2'));
}
复制代码
3. Timer
我们定义一个Timer
,timer是一个异步任务,
void TimerDemo(){
Timer.run(() {
print('异步任务');
});
print('来了');
}
复制代码
执行结果:
那么timer
是否会堵塞界面UI呢
@override void initState() {
// TODO: implement initState
super.initState();
int count = 0;
Timer.periodic(Duration(seconds: 1), (timer) {
count++;
print(count);
if(count == 99){
timer.cancel();
}
});
}
复制代码
界面并没有卡住
这里有个问题,我们切换页面的时候如果状态没有保存
,定时器没有销毁等于又建了
一个定时器
我们这个时候就需要使用dispose
,类似iOS中dealloc
中销毁定时器,我们把timer定义外部变量
,我们在页面销毁的是如果存在定时器并且定时器是在执行就销毁
@override
void dispose() {
// TODO: implement dispose
if( _timer!= null && _timer.isActive )
{
_timer.cancel();
}
print('页面销毁了');
super.dispose();
}
复制代码
我们添加个点击事件,进行循环,看下是否卡住UI
return GestureDetector(
onTap: (){
Future((){
print('start');
for(int i = 0;i<100000000000;i++){};
print('end');
});
print('点击了');
},
复制代码
卡住了,定时器都不执行了。 界面卡住了,所以我们
真正耗时操作要放在子线程执行
Future((){
compute(func,123);
});
FutureOr func(message) {
print('start');
for(int i = 0;i<100000000000;i++){};
print('end');
}
复制代码
可以点击,定时器也在执行。