Flutter总结 - Dart异步

搭完博客开始对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 不是String不能直接打印。
如果需要异步转同步那么就需要像下面一样使用提到的关键字。

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 QueueEvent 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

你可能感兴趣的:(Flutter总结 - Dart异步)