flutter 中的异步

作者: super_chao | 来源:发表于2019-10-22 16:16 被阅读0次

    以下内容从官网得到:
    https://webdev.dartlang.org/articles/performance/event-loop

    Even-Looper

    Dart是单线程模型,也就没有了所谓的主线程/子线程之分。
    Dart也是Event-Looper以及Event-Queue的模型,所有的事件都是通过EventLooper的依次执行。

    而Dart的Event Loop就是:

    • 从EventQueue中获取Event
    • 处理Event
    • 直到EventQueue为空
    image

    而这些Event包括了用户输入,点击,Timer,文件IO等

    image

    单线程模型

    一旦某个Dart的函数开始执行,它将执行到这个函数结束,也就是Dart的函数不会被其他Dart代码打断。

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

    image

    Event Queue以及Microtask Queue

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

    Microtask Queue存在的意义是:
    希望通过这个Queue来处理稍晚一些的事情,但是在下一个消息到来之前需要处理完的事情。

    当Event Looper正在处理Microtask Queue中的Event时候,Event Queue中的Event就停止了处理了,此时App不能绘制任何图形,不能处理任何鼠标点击,不能处理文件IO等等

    Event-Looper挑选Task的执行顺序为:

    • 优先全部执行完Microtask Queue中的Event
    • 直到Microtask Queue为空时,才会执行Event Queue中的Event
    image

    Dart中只能知道Event处理的先后顺序,但是并不知道某个Event执行的具体时间点,因为它的处理模型是一个单线程循环,而不是基于时钟调度(即它的执行只是按照Event处理完,就开始循环下一个Event,而与Java中的Thread调度不一样,没有时间调度的概念),也就是我们既是指定另一个Delay Time的Task,希望它在预期的时间后开始执行,它有可能不会在那个时间执行,需要看是否前面的Event是否已经Dequeue。

    异步任务调度

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

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

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

    image

    使用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);
    
    

    当需要做动画的时候,不要使用Future,而需要使用animateFrame

    PS:

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

    使用scheduleMicrotask

    在最顶层的调用关系中,使用该函数即可

    async.scheduleMicrotask(() => microtask());
    
    void microtask(){
      //  doing something
    }
    
    

    使用isolate以及Worker

    当有计算很繁重的任务时,则需要使用isolate或者Worker来执行,以保持App对用户操作的及时响应。Isolate的实现可能是一个单独的线程,或者一个单独的进程,需要看Dart VM是如何实现的。

    相关文章

      网友评论

        本文标题:flutter 中的异步

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