Flutter(十)--Widget的异步-Future、微任务、Isolate(多线程)

本次使用纯代码+注释的方式,将各个知识都展示出来

下方代码可以直接执行,通过查看log来更加深入的了解,在最后有一些理论和自己的一些理解。

/*
*   1,需要注意返回值,=>是return的简写,所以1、2、3的then是compute的后续,所以是在多线程中执行,无序的。
*   2,Future和自己的then是一体的,必定会同步执行,而scheduleMicrotask则是后续添加的所以最后执行
*
* */
void combinText() {
  Future(() => compute(comFunc, '1')).then((val) => print(val)); //1
  Future(() => compute(comFunc, '2')).then((val) => print(val));
  Future(() => compute(comFunc, '3')).then((val) => print(val));

  Future(() {
    compute(comFunc, '4');
    return '4处理';
  }).then((val) => print(val));
  Future(() {
    compute(comFunc, '5');
    return '5处理';
  }).then((val) => print(val));
  Future(() {
    compute(comFunc, '6');
    return '6处理';
  }).then((val) => print(val));

  Future(() {
    compute(comFunc, '7');
    scheduleMicrotask(() {
      print('8处理'); //2
    });
    return '7处理';
  }).then((val) => print(val));
}

/*
* computeTest是Isolate的高层封装
* */
void computeTest() {
  //创建Port
  ReceivePort port = ReceivePort();
  compute(comFunc, '初始值').then((val) => print(val));
}

String comFunc(str) {
  return '${str}处理';
}

/*
* Isolate 多线程
* Isolate 看起来更加像进程.因为有独立的内存空间!
* ReceivePort如果使用到变量,变量是进行深拷贝的值拷贝.内部修改值并不会影响外部变量本身,不用担心多线程的资源抢夺问题!不需要锁!
* */
Future<void> IsolateTest() async {
  //创建Port
  ReceivePort port = ReceivePort();
//创建isolate
  Isolate iso = await Isolate.spawn(isoFunc, port.sendPort);

  port.listen((val) {
    print('内部a=$a');
    a = val;
    port.close();
    iso.kill();
  });

  sleep(Duration(seconds: 1));
  print('外部a=$a');
}

int a = 1;

void isoFunc(SendPort port) {
  sleep(Duration(seconds: 1));
  a = 200;
  print(port);
  port.send(100);
}

//开始 , 5, 3,6,8,7,1,4,10,2,9
void testFuture4() {
  Future x1 = Future(() => null);
  x1.then((value) {
    print('6');
    scheduleMicrotask(() => print('7'));
  }).then((value) => print('8'));
  Future x = Future(() => print('1'));
  x.then((value) {
    print('4');
    Future(() => print('9'));
  }).then((value) => print('10'));

  Future(() => print('2'));
  scheduleMicrotask(() => print('3'));

  print('5');
}

/*
*  scheduleMicrotask微任务
*  在同一方法体中微任务优先级高于Future,
* */
void MicrotTest() {
  print('进入');
  Future(() {
    print('A');
    scheduleMicrotask(() {
      print('A ---- scheduleMicroTask');
    });
    return Future(() => print('A--Future'));
  }).then((value) => print('A结束'));
  scheduleMicrotask(() {
    print('scheduleMicroTask');
  });
}

/*
*  Future异步组
* 在组中是按照同步执行
* */
void FutureGroup() {
  print('进入');
  Future.wait([
    Future.sync(() {
      sleep(Duration(seconds: 2));
      print('结束1');
      return '任务一';
    }),
    Future.sync(() {
      sleep(Duration(seconds: 1));
      print('结束2');
      return '任务二';
    }),
  ]).then((value) {
    print(value);
  });
  print('结束');
}

/*
*  Future也可以同步执行
* */
void FutureSync() {
  print('进入');
  Future.sync(() {
    sleep(Duration(seconds: 1));
    print('异步操作');
  });
  print('结束');
}

//future的优先级比then低
/*
*  Future执行完之后, 会将涉及到的所有then进行一次性添加
* */
void FutureThenOrder() {
  Future(() {
    sleep(Duration(seconds: 1));
    return '第一个异步处理';
  }).then((e) {
    print(e);
    return Future(() {
      sleep(Duration(seconds: 1));
      return '第二个异步处理';
    });
  }).then((e) {
    print(e);
    return '第一个异步处理2';
  });
}

/*
* 1,FutureOr<T>表示可以返回一个Future对象或者是<T>实例
* 2,catchError在then前时,无法阻止then的执行,因为当前then实际上是在捕获catcherror这个Future
* 3, catchError的闭包返回值是依附上一层的<T>,如果上一层没有返回值,catcherror中的返回值需要单声明变量后使用
* 4, 超时
* */
Future<void> throwError() async {
  print('进入');

  Future future = Future(() {
    //1
    print('异步操作');
    sleep(Duration(seconds: 1));
//    return '异步完成';
    throw Exception('出错了');
  })
      .then((val) {
        print('第一次then:${val}');
        return '第一次then结束';
      })
      .catchError((e) {
        print('errpr:${e}');
        return '错误处理'; //3
      })
      .then((e) => print(e)) //2
      .timeout(Duration(seconds: 1)); //4
  print('结束');
}

/*
*   1,使用await以后下方所有代码都将进行同步执行
*   2,async/await必须成对出现,使用async进行方法的修饰后返回值必须也是Future<T>
* */
Future<void> getParams1() async {
  print('进入');

  await Future(() {
    sleep(Duration(seconds: 1));
    print('异步操作');
  });

  print('结束');
}

最后是自己对异步执行的一些理解,比较零散,在此做个记录。

就算是将上述代码一一执行,一定也会有一些不理解的地方,这就需要一些理论的支持。

这是从官网拿下来的图,图中清楚的展示了各种任务的执行顺序。


2-12.png
图中的解读:
  1. 一切执行都是从main函数开始。(有点废话了。。。)
  2. 微任务的执行优先级是最高的,接下来才是事件队列(future+then)
  3. 微任务、事件队列在执行完成后都会检查是否还有其他任务,而且会从原路径去检查是否有微任务->是否有事件队列的顺序,直到任务结束。
    也就是说在任务的执行过程中,又有新的任务添加,就会通过这种方式来执行。
  4. 完成之后退出。
  5. Future和then是一对属于事件队列中,必定会同步先后执行,并不是在Future执行完成后才去进行添加的。

传送门:

Flutter-汇总