1异步编程
1.1Future
factory Future(FutureOr<T> computation()) {
_Future<T> result = new _Future<T>();
Timer.run(() {
try {
result._complete(computation());
} catch (e, s) {
_completeWithErrorCallback(result, e, s);
}
});
return result;
}
Future 类表示一个异步操作结果,dart是单线程的,所以底层没有锁之类的东西,但是这不代表着dart不能异步,异步不代表多线程。
1.2 async、await
Future是用来异步执行的,而async和await搭配是用来让Future里面的某块代码同步执行的。
1.3 Future.then()
Future的所有API的返回仍是个Future对象,所以可使用Future进行链式调用。
使用then来将特定的需要等待的任务放进去,然后不堵塞后面的任务的执行。 如果then没有返回值的话,那么value就是null。
1.4 Future.catchError
1.5 Future综合使用
1.6 Future.wait
等wait里面所有任务完成后再执行then
1.7 microtask
Dart事件循环中,有两种队列:
- 事件队列(event queue)——所有的外来事件:I/O、mouse events、drawing events、timers、isolate之间的信息传递。
- 微任务队列(microtask queue)——一个短时间内就会完成的异步任务。它的优先级最高,只要队列中还有任务,就可以一直霸占着事件循环。如果微任务队列有太多微任务要处理的话,有可能会对触摸、绘制等外部事件造成阻塞卡顿。
如下图所示(图片转载自LinShunIos)
2.多线程
2.1 isolate
若将func放在Isolate里执行,则会有不同的结果
多个任务运行
可知Isolate是在子线程里面执行任务的。
Dart中的isolate有独立的内存空间,每个isolate中的数据是独立的,不存在资源抢夺,也就不需要锁。因此访问isolate的数据时不可直接访问。isolate其实就是个轻量级的进程,不独立开辟堆和栈,而是给了一个局部的内存空间,所有的变量、内存对象都在这个空间里面。isolate与原来的程序传递数据时需用到进程间的通讯。
运行发现a值并没有改变,如果要改变a值,要用到port,将port的sendPort作为参数传给func,然后添加监听数据变化来接收func里面传过来的值 。
这样a的值就改变了,由于Isolate开辟了空间,需要手动销毁Isolate。await不会堵塞后面代码的执行,因为这里是其他线程里面的。
2.2 compute
compute可返回数据并修改数据的值,加了await,会阻塞后面代码
3.异步和多线程组合
以下代码是异步执行的
稍作改动,发现是同步的
箭头函数隐藏return,所以上边的区别就是一个有return,一个没有。如果有return(即返回了子线程),则then处理的是子线程Future的结果;否则就是当前Future的结果
void isoLoadDemo() {
Future(() {
print('1开始');
return compute(testfunc, 123);
}).then((value) => {print('1结束')});
Future(() {
print('2开始');
return compute(testfunc, 123);
}).then((value) => {print('2结束')});
Future(() {
print('3开始');
return compute(testfunc, 123);
}).then((value) => {print('3结束')});
Future(() {
print('4开始');
return compute(testfunc, 123);
}).then((value) => {print('4结束')});
Future(() {
print('5开始');
return compute(testfunc, 123);
}).then((value) => {print('5结束')});
}
flutter: 1开始
flutter: 2开始
flutter: 3开始
flutter: 4开始
flutter: 5开始
flutter: 1结束
flutter: 2结束
flutter: 5结束
flutter: 3结束
flutter: 4结束
4.耗时操作在子线程异步执行
void _incrementCounter() {
Future(() => compute(testfunc, 100));
setState(() {
_counter++;
});
}
FutureOr testfunc(int message) {
print('开始');
for(int i = 0; i < 10000000000; i++) {
}
print('结束了');
}