美文网首页Flutter圈子
Flutter总结 - Dart异步

Flutter总结 - Dart异步

作者: HelloLeol | 来源:发表于2020-04-07 00:44 被阅读0次

    搭完博客开始对flutter进行简单的总结
    跳过一些基础的使用方法,主要对涉及使用到但是不清楚的部分学习归纳

    Future async await

    异步是开发过程躲不开的一个问题(处理网络又不能忽略前台响应),这次先介绍dart里面以下几个关键词:

    Future:一种class类型,表示一种不会立即完成的计算过程。
    async:关键字 用来修饰方法表示该方法异步,存在耗时的时候使用。
    await:异步转同步,会等到该方法执行完成后再继续执行。

    首先dart其实并不存在多线程,采取类似JS的事件方式实现异步,具体后面总结。
    官网在介绍这一张时给出了一个很好的例子

    String createOrderMessage () {
      var order = fetchUserOrder();
      return 'Your order is: $order';
    }
    
    Future<String> 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> 不是String不能直接打印。
    如果需要异步转同步那么就需要像下面一样使用提到的关键字。

    Future<String> fetchUserOrder() {
      // Imagine that this function is more complex and slow.
      return Future.delayed(Duration(seconds: 4), () => 'Large Latte');
    }
    
    Future<void>main() 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";
    }
    
    Future<void>main() 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<String> 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来进行异步? 也不是。具体实现如下

    1⃣️当主isolate通过进行初始化运行之后,会立刻建立两个队列MicroTask QueueEvent Queue

    2⃣️运行main函数,触发完成后进行下一步。

    3⃣️运行Event Loop

    [站外图片上传中...(image-9db77f-1586191438831)]

    有点像加强版的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异步

        本文链接:https://www.haomeiwen.com/subject/tgpwphtx.html