搭完博客开始对flutter进行简单的总结
跳过一些基础的使用方法,主要对涉及使用到但是不清楚的部分学习归纳
Future async await
异步是开发过程躲不开的一个问题(处理网络又不能忽略前台响应),这次先介绍dart里面以下几个关键词:
Future:一种class类型,表示一种不会立即完成的计算过程。
async:关键字 用来修饰方法表示该方法异步,存在耗时的时候使用。
await:异步转同步,会等到该方法执行完成后再继续执行。
首先dart其实并不存在多线程,采取类似JS的事件方式实现异步,具体后面总结。
官网在介绍这一张时给出了一个很好的例子
String createOrderMessage () {
var order = fetchUserOrder();
return 'Your order is: $order';
}
Future fetchUserOrder() {
// Imagine that this function is more complex and slow
return Future.delayed(Duration(seconds: 4), () => 'Large Latte');
}
void main () {
print(createOrderMessage());
}
运行后会出现异常,动态类型出错,第三行的order是Future
如果需要异步转同步那么就需要像下面一样使用提到的关键字。
Future fetchUserOrder() {
// Imagine that this function is more complex and slow.
return Future.delayed(Duration(seconds: 4), () => 'Large Latte');
}
Futuremain() async{
print('Awaiting user order...');
var order = await fetchUserOrder();
print('Your order is: $order');
}
在使用的地方用await修饰Future,并且用async修饰方法,才可以实现异步转同步。
即例子中成功获得用户思考4秒后给出的点单类型。
但是要注意下面几个基本问题:
如果只有await没有async会直接报错。
如果有async没有await不会报错,但是异步不会转为同步。
如果有await修饰的返回值不是Future也不会有任何效果。
String fetchUserOrder() {
countSeconds(4);
return "xxx";
}
Futuremain() async{
print('Awaiting user order...');
var order = await fetchUserOrder();
print('Your order is: $order');
}
void countSeconds(s) {
for( var i = 1 ; i <= s; i++ ) {
Future.delayed(Duration(seconds: i), () => print(i));
}
}
比如上面这个例子,使用await修饰的函数返回的是String,但下面一行并不会等到记数之后执行。
Future的更多用法
上面的例子是一种最基本的用法,在网络访问中,按上面的结构会嵌套很深。Dart为网络场景(当然也不光只有网络访问可以使用),提供了一套类似于Promise的链式调用方法。见注释。
Future fetchUserOrder() {
// Imagine that this function is more complex and slow
return Future
.delayed(Duration(seconds: 4), () => 'Large Latte')
.then((value) => value) // 对值进行处理
.catchError(() => print('catch error')) // 捕获异常
.whenComplete(() => print('completed'));// 类似于final
}
延伸
从上面可以看到每次都是用Future.delayed开启一个“新的线程”,但是上面不是又说了dart是单线程语言?
首先,dart并无传统的线程概念,取而代之的是isolate。每一个isolate之间不共享内存,单独运行。官方给出的解释是:
在应用运行中UI创建回收过程十分频繁,隔离设计可以方便快速进行垃圾管理。
isolate以后进行介绍,那么Future是不是开了一个isolate来进行异步? 也不是。具体实现如下
① 当主isolate通过进行初始化运行之后,会立刻建立两个队列MicroTask Queue和Event Queue。
② 运行main函数,触发完成后进行下一步。
③ 运行Event Loop。
有点像加强版的Android Handler,不同的是拥有了两个队列往loop里面传递事件。
MicroTask:一些不耗时快速完成的任务,可以使用scheduleMicroTask()
直接向队列里面传入任务。
Event:执行一些较耗时的任务,在MicroTask为空时,会从Event里面读取任务进行运行。Future实现异步也是依靠这个队列。
参考资料:
https://web.archive.org/web/20170704074724/https://webdev.dartlang.org/articles/performance/event-loop
https://medium.com/dartlang/dart-asynchronous-programming-isolates-and-event-loops-bffc3e296a6a
https://medium.com/@devexps/flutter-execute-code-with-microtask-queue-and-event-queue-f2dc10b06aad
https://dart.cn/codelabs/async-await