Flutter--Future原理

一、什么是Future?

简单来说future就是一个Future对象,当执行return await。。。的时候,实际上返回的是一个延迟计算的Future对象,这个Future对象是Dart内置的,有自己的队列策略,它将要操作的事件放入EventQueue中,在队列中的事件按照先进先出的原则去逐一处理事件,当事件处理完成后,将结果返回给Future对象。

在这个过程中涉及到了异步和等待:

异步:就是不用阻塞当前线程,来等待该线程任务处理完成再去执行其他任务。
等待:await,声明运算为延迟执行

二、async和await

首先看一个例子:

getData() async{
   return await http.get(Uri.encodeFull(url), headers: {"Accept": "application/json"});
}
//然后调用函数来获取结果
String data = getData();

这段代码在运行的时候会报错。因为data是String类型,而函数getData()是一个异步操作函数,其返回值是一个await延迟执行的结果。
在Dart中,有await标记的运算,结果都是一个Future对象,Future不是String类型,所以就报错了。

如何获取异步函数的结果呢?Dart规定有async标记的函数,只能由await来调用,那么我们可以在函数前面加一个await关键字:

String data=await getData();

但是这违背了await必须要在async标记的函数中使用,所以赋值代码可以改成:

String data;
setData() async {
  data = await getData();    //getData()延迟执行后赋值给data
}

总结:
async和await的使用其实就只有两点:

1、await关键字必须在async函数内部使用
2、调用async函数必须使用await关键字

三、Dart异步

Dart是单线程模型,是一种Event-Looper以及Event-Queue的模型,所有的事件都是通过EventLooper的依次执行。

Event Loop的执行顺序

从EventQueue中获取Event,处理Event直到EventQueue为空。
在这里插入图片描述Event即事件,包括输入,点击,Timer,文件IO等

在这里插入图片描述
四、单线程模型
所谓单线程,就是一旦一个函数开始执行,就必须将这个函数执行完,才能去执行其他函数。

Dart中没有线程的概念,只有isolate,每个isolate都是隔离的,并不会共享内存。一个Dart程序是在Main isolate中的main函数开始,而在Main函数结束后,Main isolate线程开始一个个(one by one)的处理Event Queue中的每一个Event。

在这里插入图片描述

五、Event Queue、Microtask Queue

Dart中的Main Isolate只有一个Event Looper,但是存在两个Event Queue:

1、Event Queue(事件队列)
2、Microtask Queue(微任务队列)
这两者之间的关系可以用一张图来说明:
在这里插入图片描述
3、Microtask Queue中的Event优先被处理
4、直到Microtask Queue队列中的Event为空时,才会去执行Event Queue中的Event

六、异步任务调度

当有代码可以在后续任务执行的时候,有两种方式,通过dart:async这个Lib中的API即可:

使用Future类,可以将任务加入到Event Queue的队尾
使用scheduleMicrotask函数,将任务加入到Microtask Queue队尾

当使用EventQueue时,需要考虑清楚,尽量避免microtask queue过于庞大,否则会阻塞其他事件的处理

在这里插入图片描述

七、Future的使用

一般常用的Future构造函数:

new Future((){
    //  doing something
});

而一般常用的还有当有分治任务时,需要将一个大任务拆成很多小任务一步步执行时,就需要使用到Future.then函数来拆解任务:

void main(){
new Future(() => futureTask)  //  异步任务的函数
        .then((m) => "futueTask execute result:$m")  //   任务执行完后的子任务
        .then((m) => m.length)  //  其中m为上个任务执行完后的返回的结果
        .then((m) => printLength(m))
        .whenComplete(() => whenTaskCompelete);  //  当所有任务完成后的回调函数
}

int futureTask() {
    return 21; 
}

void printLength(int length) {
    print("Text Length:$length");
}

void whenTaskCompelete() {
    print("Task Complete");
}

当任务需要延迟执行时,可以使用new Future.delay来将任务延迟执行,而如上所述,只有当Main isolate的Event Queue处于Idle的状态时,才会延迟1s执行,否则等待的时间会比1s长很多

new Future.delayed(const Duration(seconds: 1), () => futureTask);

八、Tips

1、Future中的then并没有创建新的Event丢到Event Queue中,而只是一个普通的Function Call,在FutureTask执行完后,立即开始执行
2、当Future在then函数先已经执行完成了,则会创建一个task,将该task的添加到microtask queue中,并且该任务将会执行通过then传入的函数
3、Future只是创建了一个Event,将Event插入到了Event Queue的队尾
4、使用Future.value构造函数的时候,就会和第二条一样,创建Task丢到microtask Queue中执行then传入的函数
5、Future.sync构造函数执行了它传入的函数之后,也会立即创建Task丢到microtask Queue中执行。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值