美文网首页
Flutter学习(九)Dart异步

Flutter学习(九)Dart异步

作者: yanhooIT | 来源:发表于2020-04-22 00:42 被阅读0次

Dart是如何完成耗时操作的?

  • Dart完成耗时操作的原理是:基于单线程 + 事件循环(Event Loop)来完成耗时操作,且这些耗时操作都是非阻塞式调用
  • 另外:你要知道Dart是单线程的,那他是如何搞定异步的呢?(下面会分析)

概念补充

  • 阻塞式调用和非阻塞式调用
    • 阻塞式调用:调用结果返回之前,当前线程会被挂起,调用线程只有在得到调用结果之后才会继续执行
    • 非阻塞式调用:调用执行之后,当前线程继续执行,只需要过一段时间来检查一下有没有结果返回即可
  • 事件循环
    • 将需要处理的一系列事件(包括点击事件、IO事件、网络事件)放在一个事件队列(Event Queue)
    • 不断的从事件队列(Event Queue)中取出事件,并执行,直到事件队列中所有事件都被执行了为止

Dart是如何搞定异步的?

  • Dart中的异步操作主要使用Future以及async、await,即:实现非阻塞式调用
Future
  • 通过Future实现异步调用
import 'dart:io';

main(List<String> args) {
  print("main start");

  // 模拟一个网络请求
  var future = getNetworkData();

  // 通过.then(成功回调函数)的方式来监听Future内部执行完成时获取到的结果
  future.then((String value) {
    print(value);
  })
  // 通过.catchError(失败或异常回调函数)的方式来监听Future内部执行失败或者出现异常时的错误信息
  .catchError((err) {
    print(err);
  })
  // 这里是一定会执行的
  .whenComplete(() {
    print("代码执行完毕");
  });

  print("main end");
}

Future<String> getNetworkData() {
  return Future<String>(() {// 将耗时的操作包裹到Future的回调函数中
    // 模拟网络请求
    sleep(Duration(seconds: 3));

    // 模拟有返回结果, 那么就执行Future对应的then的回调
    return "result";

    // 模拟有错误信息, 需要在Future回调中抛出一个异常
    // throw Exception("我是错误信息");
  });
}
  • Future的链式调用
import 'dart:io';

main(List<String> args) {
  print("main start");

  // Future的链式调用
  Future(() {
    // 1.发送第一次请求
    sleep(Duration(seconds: 3));
    return "第一次的结果";
  }).then((res) {
    print(res);

    // 2.发送的第二次请求
    sleep(Duration(seconds: 2));
    return "第二次的结果";
    // throw Exception("第二次异常");
  }).then((res) {
    print(res);

    // 3.发送的第三次请求
    sleep(Duration(seconds: 1));
    return "第三次的结果";
  }).then((res) {
    print(res);
  }).catchError((err) {
    // 捕获异常
    print(err);
  });

  print("main end");
}
  • Future其他接口补充
main(List<String> args) {
  /** 打印结果
   * futureValueMethod start
   * futureValueMethod end
   * 哈哈哈
   * 
   * 为什么“哈哈哈”是在最后打印的呢???
   *  因为Future中的then会作为新的任务会加入到事件队列中(Event Queue),加入之后你肯定需要排队执行了
   */
  // futureValueMethod();

  /** 打印结果
   * futureErrorMethod start
   * futureErrorMethod end
   * 错误信息
   * 
   * 为什么“错误信息”是在最后打印的呢???
   *  答案如上所述
   */
  // futureErrorMethod();

  /** 打印结果
   * futureDelayedMethod start
   * futureDelayedMethod end
   * result
   */
  futureDelayedMethod();
}

void futureValueMethod() {
  print("futureValueMethod start");
  
  // 直接获取一个完成的Future,该Future会直接调用then的回调函数
  Future.value("哈哈哈").then((res) {
    print(res);
  });
  
  print("futureValueMethod end");
}

void futureErrorMethod() {
  print("futureErrorMethod start");
  
  // 直接获取一个完成的Future,但是一个发生异常的Future,该Future会直接调用catchError的回调函数
  Future.error("错误信息").catchError((err) {
    print(err);
  });
  
  print("futureErrorMethod end");
}

void futureDelayedMethod() {
  print("futureDelayedMethod start");
  
  // 延迟一定时间后执行回调函数,执行完回调函数后会执行then的回调
  Future<String>.delayed(Duration(seconds: 3), () {
    return "result";
  }).then((res) {
    print(res);
  });
  
  print("futureDelayedMethod end");
}
async、await
  • 通过这两个关键字可以让我们用同步的代码格式,去实现异步的调用过程
  • 通常一个async的函数会返回一个Future
  • 通过async、await完成网络请求
import 'dart:io';

main(List<String> args) {
  print("main start");

  var result = getNetworkData().then((res) {
    print(res);
  });
  print(result);

  print("main end");
}

/**
 * 解决两个问题:
 *  1.await必须在async函数中才能使用
 *  2.async函数返回的结果必须是一个Future
 *  3.返回值会默认被包装在一个Future中
 */
Future getNetworkData() async {
  await sleep(Duration(seconds: 3));
  return "Hello World";
}
  • 通过async、await实现链式调用
import 'dart:io';

main(List<String> args) {
  print("main start");

  /** 打印结果
  * main start
  * main end
  * argument1
  * argument12
  * argument123
  */
  getData().then((res) {
    print(res);
  }).catchError((err) {
    print(err);
  });

  print("main end");
}

Future getData() async {
  // 调用第1次网络请求
  var res1 = await getNetworkData("argument1");
  print(res1);

  // 调用第2次网络请求
  var res2 = await getNetworkData(res1+"2");
  print(res2);

  // 调用第3次网络请求
  var res3 = await getNetworkData(res2+"3");
  return res3;
}

Future getNetworkData(String arg) {
  return Future(() {
    sleep(Duration(seconds: 3));
    return arg;
  });
}

Isolate

  • Dart是单线程的,这个线程有自己可以访问的内存空间以及事件循环,我们可以将这个空间系统称之为是一个Isolate
  • 在 Isolate 中,资源隔离做得非常好,每个 Isolate 都有自己的 Event LoopQueue
  • Isolate 之间不共享任何资源,只能依靠消息机制通信,因此也就没有资源抢占问题
  • 如果只有一个Isolate,那么意味着我们只能永远利用一个线程,这对于多核CPU来说,是一种资源的浪费
  • 在开发中,我们有非常多耗时的计算,完全可以自己创建Isolate,在独立的Isolate中完成想要的计算操作
  • 创建Isolate
import 'dart:isolate';

main(List<String> args) {
  print("main start");

  // 开启一个新的Isolate
  Isolate.spawn(calc, 100);

  print("main end");
}

void calc(int count) {
  var total = 0;
  for (var i = 0; i < count; i++) {
    total += i;
  }
  print(total);
}
  • Isolate通信机制(这里只是单向通信)
import 'dart:isolate';

main(List<String> args) async {
  print("main start");

  // 1.创建管道
  ReceivePort receivePort = ReceivePort();

  // 2.创建新的Isolate
  Isolate isolate = await Isolate.spawn<SendPort>(foo, receivePort.sendPort);

  // 3.监听管道消息
  receivePort.listen((message) {
    print("message: $message");

    // 不再使用时,我们会关闭管道
    receivePort.close();
    // 需要将isolate杀死
    isolate?.kill(priority: Isolate.immediate);
  });

  print("main end");
}

void foo(SendPort send) {
  return send.send("Hello Flutter");
}
  • Flutter提供了支持并发计算的compute函数,它内部封装了Isolate的创建和双向通信,注意:不是dart的API,而是Flutter的API,所以只有在Flutter项目中才能运行
// 此代码必须在Flutter项目中才能运行
main(List<String> args) async {
  int result = await compute(powerNum, 5);
  print(result);
}

int powerNum(int num) {
  return num * num;
}

相关文章

  • Flutter学习(九)Dart异步

    Dart是如何完成耗时操作的? Dart完成耗时操作的原理是:基于单线程 + 事件循环(Event Loop)来完...

  • 2019-09-23: 十一:Flutter之Dart异步操作?

    十一:Flutter之Dart异步操作? 1: Dart 的异步模型?我们先搞清楚dart是如何搞定异步操作的?1...

  • @@@@@@@@

    \009-享学课堂安卓架构第一期├01 flutter│ ├Dart异步编程(1)-.mp4│ ├Dart异步...

  • Dart基础入门

    Flutter应用是采用Dart语言来编写,在学习Flutter之前,我们有必要先学习一下Dart语言。Dart是...

  • Flutter基础入门(三)Dart快速入门

    前言 Dart是Flutter SDK指定的语言,因此要学习Flutter,Dart是必须掌握的。关于Dart可以...

  • 深入理解Flutter/Dart事件机制

    前言 在前文《Flutter/Dart中的异步》[https://juejin.cn/post/684490376...

  • 浅谈Dart语言

    前言 Dart是Flutter SDK指定的语言,因此要学习Flutter,Dart是必须掌握的。 2. Dart...

  • flutter开发入门

    中文 学习网站 Flutter官网[https://flutter.cn/] Dart语言学习 Dart官网[ht...

  • FutureBuilder

    Flutter和Dart是异步的,使用Dart的Futures可以管理IO,不用担心线程死锁等问题,但是如何在使用...

  • Dart 基础

    为什么学习dart?谷歌推出了flutter,而flutter是基于dart语言的 dart是函数式编程语言 所有...

网友评论

      本文标题:Flutter学习(九)Dart异步

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