Flutter小技巧|异步编程之多Future与Microtask

281 阅读3分钟

「这是我参与11月更文挑战的第15天,活动详情查看:2021最后一次更文挑战

Hi 👋

我的个人项目扫雷Elic 无尽天梯梦见账本隐私访问记录
类型游戏财务工具
AppStoreElicUmemi隐私访问记录

更多专栏:

Lawliet的独立开发碎碎念

Lawliet的iOS游园会

Lawliet的iOS底层实验室

Lawliet的iOS逆向实验室

Lawliet的刷题小本本

Lawliet的Flutter实验室

Flutter小技巧|从侧索引条封装看手势处理与clamp函数

Flutter小技巧|Widget初始化方法重写&链式调用&排序

Flutter小技巧|通过多样式Cell看断言

Flutter小技巧|ListView滑动到分组头部

Flutter小技巧|第三方库导入与网络数据展示(三种形式)

Flutter小技巧|标签页面子页面切换数据保留:Mixin与PageView

Flutter小技巧|异步编程之初识Future

上文异步编程之初识Future我们初步了解了使用 Future 异步编程,本文就将结合更多场景了解异步编程。

多个 Future

下面多个 Future 的执行顺序会是什么样的呢?

void main() {
  Future( () {
    sleep(const Duration(seconds: 1));
    return "${DateTime.now()}: 1";
  })
  .then((value){
    print(value);
  });

  Future( () {
    sleep(const Duration(seconds: 1));
    return "${DateTime.now()}: 2";
  })
      .then((value){
    print(value);
  });

  Future( () {
    sleep(const Duration(seconds: 1));
    return "${DateTime.now()}: 3";
  })
      .then((value){
    print(value);
  });

  Future( () {
    sleep(const Duration(seconds: 1));
    return "${DateTime.now()}: 4";
  })
      .then((value){
    print(value);
  });
}

分析: 多个 Future 是按照代码顺序,依次添加到任务队列的,会依次被执行。所以会按顺序输出。

flutter: 2021-11-27 15:34:53.829132: 1
flutter: 2021-11-27 15:34:54.855321: 2
flutter: 2021-11-27 15:34:55.863015: 3
flutter: 2021-11-27 15:34:56.870869: 4

依赖连续调用

如果有几个异步任务是有一定的顺序或者结果依赖的,那么可以通过 then 的链式调用进行:

int number = 1;

void main() {
  Future(() {
    sleep(const Duration(seconds: 1));
    number += 1;
    print("${DateTime.now()}: $number");
    return number;
  }).then((value) {
    sleep(const Duration(seconds: 1));
    value += 1;
    print("${DateTime.now()}: $value");
    return value;
  }).then((value) {
    sleep(const Duration(seconds: 1));
    value += 1;
    print("${DateTime.now()}: $value");
    return value;
  }).then((value) {
    sleep(const Duration(seconds: 1));
    value += 1;
    print("${DateTime.now()}: $value");
    return value;
  });
}

输出的结果:

flutter: 2021-11-27 15:43:29.512735: 2
flutter: 2021-11-27 15:43:30.537787: 3
flutter: 2021-11-27 15:43:31.544347: 4
flutter: 2021-11-27 15:43:32.549391: 5

多个无依赖的任务结束后处理

开发中,我们还会遇到一些多个异步任务都执行完再去做一些事情的场景。 Future 也有提供这种歌场景的功能:

void main() {
  Future.wait([
    Future(() {
      sleep(Duration(seconds: 1));
      print('${DateTime.now()}: 1');
      return "任务1";
    }),
    Future(() {
      sleep(Duration(seconds: 1));
      print('${DateTime.now()}: 2');
      return "任务2";
    }),
    Future(() {
      sleep(Duration(seconds: 1));
      print('${DateTime.now()}: 3');
    }),
    Future(() {
      sleep(Duration(seconds: 1));
      print('${DateTime.now()}: 4');
    }),
    Future(() {
      sleep(Duration(seconds: 1));
      print('${DateTime.now()}: 5');
      return "任务5";
    }),
  ]).then((value) {
    print(value);
  });
}

输出:

flutter: 2021-11-27 15:50:47.972739: 1
flutter: 2021-11-27 15:50:49.000895: 2
flutter: 2021-11-27 15:50:50.008548: 3
flutter: 2021-11-27 15:50:51.015465: 4
flutter: 2021-11-27 15:50:52.023024: 5
flutter: [任务1, 任务2, null, null, 任务5]

这里和使用单个 Future 一样,也可以通过 then 来处理结果。通过输出内容我们可以发现,这里的 then 里的 value 其实是一个数组,并且如果数组内部的顺序是和 Future 数组的顺序保持一致的。

scheduleMicrotask

scheduleMicrotask 也是异步编程常用的一个 API,它的优先级比 Future 会高,同一队列中,会优先将 微任务 处理完成再去处理 Future

题目

这里通过一个题目考验一下:

void main() {
  Future((){
    print('1');
  }).then((value){
    print('2');
    scheduleMicrotask((){
      print('3');
    });
  }).then((value){
    print('4');
  });

  scheduleMicrotask((){
    print('5');
  });

  Future((){
    print('6');
  });

  scheduleMicrotask((){
    print('7');
  });

  print('8');
}

思考一下这里的输出会是什么样的顺序呢?

不要运行,欢迎在评论中留下你的答案。