「这是我参与11月更文应战的第8天,活动详情检查:2021最终一次更文应战」

Future异步

在上面网络恳求的时分用到了Future,那么这个究竟是什么?Fluture是主线程傍边的异步代码

  1. 下面打印的次序是什么:
void main() {
  testFuture();
  print('A');
}
void testFuture() async {
  Future(() {
    print('C');
  });
  print('B');
}

Flutter实战-异步与多线程

  1. 参加await之后打印的次序是什么?
void main() {
  testFuture();
  print('A');
}
void testFuture() async {
  await Future(() {
    print('C');
  }).then((value) => print('D'));
  print('B');
}

Flutter实战-异步与多线程

通过测验发现运用Future润饰的代码块会异步履行,不会卡住当时的线程。如果希望在这个异步使命履行完结之后再操作,需求在Future前面加上一个await。

  1. 多个Future并行的时分的打印次序:
void main() {
  testFuture();
  print('A');
}
void testFuture() async {
  Future(() {
    return '使命1';
  }).then((value) => print('$value 履行完毕'));
  Future(() {
    return '使命2';
  }).then((value) => print('$value 履行完毕'));
  Future(() {
    return '使命3';
  }).then((value) => print('$value 履行完毕'));
  Future(() {
    return '使命4';
  }).then((value) => print('$value 履行完毕'));
  print('使命增加完毕');
}

Flutter实战-异步与多线程

调整次序或者是让其间的一个使命参加睡觉等多项测验之后,发现多个Future并行发现这个履行的次序便是增加的次序。

  1. 有依赖关系的Future打印次序:
void testFuture() async {
  Future(() {
    return '使命1';
  }).then((value) {
    print('$value完毕');
    return '$value使命2';
  }).then((value) {
    print('$value完毕');
    return '$value使命3';
  }).then((value) {
    print('$value完毕');
    return '$value使命4';
  });
}

Flutter实战-异步与多线程

  1. 多个Future履行完结之后再操作:
void testFuture() async {
  Future.wait([
    Future(() {
      return '使命1';
    }),
    Future(() {
      return '使命2';
    }),
    Future(() {
      return '使命3';
    }),
    Future(() {
      return '使命4';
    }),
  ]).then((value) => print('$value')); // wait里边的履行次序也是增加的次序
}

Flutter实战-异步与多线程

  1. scheduleMicrotask能够插队到Future使命前面
void testFuture() async {
  Future.wait([
    Future(() {
      return '使命1';
    }),
    Future(() {
      return '使命2';
    }),
    Future(() {
      return '使命3';
    }),
    Future(() {
      return '使命4';
    }),
  ]).then((value) => print('$value'));
  scheduleMicrotask(() {
    print('scheduleMicrotask');
  });
}

Flutter实战-异步与多线程

Dart中就只有两种行列:一种是事件行列,一种是微使命行列,微使命行列的优先级一直高于事件行列。 下图为官方图:

Flutter实战-异步与多线程

  1. 下列打印的次序是什么?
void testFuture() async {
  Future x = Future(() => print('A'));
  Future(() => print('B'));
  scheduleMicrotask(() {
    print('C');
  });
  x.then((value) => print('D'));
  print('E');
}

Flutter实战-异步与多线程

首要肯定是主线程的E,然后是微使命的C,剩余的两个Future依照增加的次序履行,首要履行A和D最终是B

  1. Fluture嵌套微使命的履行次序:
void testFuture() async {
  Future(() => print('A')).then((value) {
    scheduleMicrotask(() {
      print('D');
    });
  }).then((value) => print('F'));
  Future(() => print('B'));
  scheduleMicrotask(() {
    print('C');
  });
  print('E');
}

Flutter实战-异步与多线程

这儿能够这么了解:then后边的代码能够了解为丢到了微使命行列去履行。

补充:运用Flutter的时分尽量运用链式调用,保证在最终调用.catchError来捕获异常

getData() async {
  print('开始了');
  await Future(() {
    for (int i = 0; i < 100; i++) {}
    return '循环完毕';
  })
      .then((value) => print('$value'))
      .whenComplete(() => print('完结了'))
      .catchError((e) => print(e.toString()));
  print('await之后的代码');
}

Dart中的多线程

Dart傍边的Isolate更像一个进程,有独立的内存空间。意味着每个进程之间的数据是独立的,不存在争夺空间的情况,所以不需求锁的概念。

void main() {
  IsolateDemo();
}
void IsolateDemo() {
  print('1');
  Isolate.spawn(func, 3);
  Isolate.spawn(func, 4);
  Isolate.spawn(func, 5);
  Isolate.spawn(func, 6);
  Isolate.spawn(func, 7);
  Isolate.spawn(func, 8);
  Isolate.spawn(func, 9);
  sleep(Duration(seconds: 3));
  print('2');
}

Flutter实战-异步与多线程
上面说了不存在同一块内存的问题,咱们也来验证一下,在下面的代码中,我在Isolate中修改了a的值,那么最终打印的a=?

int a = 100;
void IsolateDemo() {
  print('1');
  Isolate.spawn(func, 3);
  Isolate.spawn(func, 4);
  Isolate.spawn(func, 5);
  Isolate.spawn(func, 6);
  Isolate.spawn(func, 7);
  Isolate.spawn(func, 8);
  Isolate.spawn(func, 9);
  sleep(Duration(seconds: 3));
  print('2');
  print('a = $a');
}
func(int count) {
  print('$count');
  a = count;
}

Flutter实战-异步与多线程
经验证,最终a还是等于100.也便是说在Isolate中的修改并没有效果。 ​

ReceivePort & Isolate

void IsolateDemo() {
  print('1');
  ReceivePort port = ReceivePort();
  Isolate.spawn(func, port.sendPort);
  port.listen((message) {
    print('message=$message');
  });
  sleep(Duration(seconds: 3));
  print('2');
}
func(SendPort port) {
  port.send(10);
}

Flutter实战-异步与多线程

上面的代码还是有一点需求完善的当地:此时注意需求手动的封闭端口和销毁Isolate

void IsolateDemo() async {
  print('1');
  ReceivePort port = ReceivePort();
  Isolate iso = await Isolate.spawn(func, port.sendPort);
  port.listen((message) {
    print('message=$message');
    port.close();
    iso.kill();
  });
  sleep(Duration(seconds: 3));
  print('2');
}

compute

用法跟Isolate差不多,是在Isolate上的进一步包装。compute不需求手动kill

void main() {
  Comouterdemo();
}
void Comouterdemo() {
  print('1');
  compute(func1, 10);
  sleep(Duration(seconds: 3));
  print('2');
}
func1(int num) {
  print('$num');
}

Flutter实战-异步与多线程

调配await异步运用

void main() {
  Comouterdemo();
}
void Comouterdemo() async {
  print('1');
  int result = await compute(func1, 10);
  sleep(Duration(seconds: 3));
  print('result=$result');
  print('2');
}
int func1(int num) {
  print('$num');
  return num;
}

Flutter实战-异步与多线程

一些小知识

  • 关于import, as关键字便是给库起别名,意图是避免类名、方法名抵触import 'package:http/http.dart' as http;
  • 导入库,默许是整个文件都会导入,如果需求指定的话有两个关键字。show:履行需求导入的内容;hide:需求隐藏的内容
  • pubspec.yamlpublish_to:指定发布到哪里去,默许的都是到pub.dev里边去
  • pubspec.yamlversion: 当时项意图版别号
  • pubspec.yaml中 Dart的版别environment:sdk: ">=2.12.0 <3.0.0"
  • pubspec.yamldev_dependencies: 开发环境依赖的版别打包的时分不会有这些
  • pubspec.yamldependencies: 第三方库导入位置。dio:^4.0.1大版别不变的区间写法,相当于>=4.0.1 <5.0.0; dio:4.0.1指定4.0.1版别; dio:any恣意版别