Flutter中async与await异步编程原理分析

简介: 大部分操作系统(如Windows、Linux)的任务调度是采用时间片轮转的抢占式调度方式,对于单核CPU来讲,并行执行两个任务,实际上是CPU在进行着快速的切换,对用户来讲感觉不到有切换停顿,就好比220V交流电灯光显示原理一样,也就是说一个任务执行一小段时间后强制暂停去执行下一个任务,每个任务轮流执行。

Flutter中async与await异步编程原理分析

题记
—— 执剑天涯,从你的点滴积累开始,所及之处,必精益求精,即是折腾每一天。
异步编程原理分析.png

** 你可能需要
CSDN 网易云课堂教程
掘金 EDU学院教程
知乎 Flutter系列文章

在写过几篇异步编程的使用后,是时候于大家分享下Flutter异步编程的原理了。

Header1 Header2
Flutter延时任务、Flutter通过Future与Timer实现延时任务 Flutter异步编程async与await的基本使用
Flutter异步编程async与await的基本使用 Flutter异步加载FutureBuilder重绘解决方案

1异步编程基本概念

1.1 任务调度

先谈谈任务调度 ,大部分操作系统(如Windows、Linux)的任务调度是采用时间片轮转的抢占式调度方式,对于单核CPU来讲,并行执行两个任务,实际上是CPU在进行着快速的切换,对用户来讲感觉不到有切换停顿,就好比220V交流电灯光显示原理一样,也就是说一个任务执行一小段时间后强制暂停去执行下一个任务,每个任务轮流执行。
任务执行的一小段时间叫做时间片,任务正在执行时的状态叫运行状态,任务执行一段时间后强制暂停去执行下一个任务,被暂停的任务就处于就绪状态等待下一个属于它的时间片的到来,任务的停与执行切换,称之为任务调度。

1.2 进程

计算机的核心是CPU,它承担了所有的计算任务,而操作系统是计算机的管理者,它负责任务的调度、资源的分配和管理,操作系统中运行着多个进程,每一个进程是一个具有一定独立功能的程序在一个数据集上的一次动态执行的过程,是应用程序运行的载体。
操作系统会以进程为单位,分配系统资源(CPU时间片、内存等资源),进程是资源分配的最小单位,也就是操作系统的最小单位。

1.3 线程

线程是进程中的概念,一个进程中可包含多个线程。
任务调度采用的是时间片轮转的抢占式调度方式,进程是任务调度的最小单位。
默认情况下,一般一个进程里只有一个线程,进程本身就是线程,所以线程可以被称为轻量级进程。

1.4 协程(Coroutines)

协程,是一种基于线程,但又比线程更加轻量级的存在,是线程中的概念,一个线程可以拥有多个协程。

在传统的J2EE体系中都是基于每个请求占用一个线程去完成完整的业务逻辑(包括事务)。所以系统的吞吐能力取决于每个线程的操作耗时。如果遇到很耗时的I/O行为,则整个系统的吞吐立刻下降,因为这个时候线程一直处于阻塞状态,如果线程很多的时候,会存在很多其他的线程处于等待,空闲状态(等待前面的线程执行完才能执行),造成了资源应用不彻底。

最常见的例子就是同步阻塞的JDBC,在连接过程中线程根本没有利用CPU去做运算,而是处在等待状态,而另外过多的线程,也会带来更多的ContextSwitch(上下文切换)开销。

协程的出现,当出现长时间的I/O操作时,通过让出当前占用的任务通道,执行下一个任务的方式,通过在线程中实现调度,来消除ContextSwitch上的开销,避免了陷入内核级别的上下文切换造成的性能损失,进而突破了线程在IO上的性能瓶颈。从编程角度上看,协程的思想本质上就是控制流的主动让出(yield)和恢复(resume)机制。

2 Flutter 项目中的异步编程原理

如使用Flutter开发的APP安装在手机上,当点击APP图标启动时,手机操作系统会为当前APP创建一个进程,然后在Flutter项目中通过main函数启动Flutter构建的项目。

Dart是基于单线程模型的语言,所以在Flutter中我们一般的异步操作,实际上还是通过单线程通过调度任务优先级来实现的。

在Dart中的线程机制,称为isolate,在Flutter项目中, 运行中的 Flutter 程序由一个或多个 isolate 组成,默认情况下启动的Flutter项目,通过main函数启动就是创建了一个main isolate,后续会有专门一文来论述isolate的开发使用,在这里我们 main isolate 为Flutter的主线程,或者是UI线程。

2.1 Dart事件循环

单线程模型中主要就是在维护着一个事件循环(Event Loop) 与 两个队列(event queue和microtask queue)

当Flutter项目程序触发如点击事件、IO事件、网络事件时,它们就会被加入到eventLoop中,eventLoop一直在循环之中,当主线程发现事件队列不为空时发现,就会取出事件,并且执行。

microtask queue只处理在当前 isolate 中的任务,优先级高于event queue,好比机场里的某个VIP候机室,总是VIP用户先登机了,才开放公共排队入口,如果在event事件队列中插入microtask,当当前event执行完毕即可插队执行microtask事件,microtask queue队列的存在为Dart提供了给任务队列插队的解决方案。

当事件循环正在处理microtask事件时的时候,event queue会被堵塞。这时候app就无法进行UI绘制,响应鼠标事件和I/O等事件。

这两个任务队列中的任务切换就相当于是协程调度机制。

2.2 Future 概述

Future就是event,每一个被await标记的句柄也是一个event,timer创建的任务也是一个event,每创建一个Future就会把这个Future扔进event queue中排队。

使用async和await组合,即可向event queue中插入event实现异步操作。

Future最主要的功能就是提供了链式调用方式以及完整的一套处理异步任务的方法。

2.3 Future 的常用方法概述

Flutter提供了下面三个方法,让我们来注册回调,来监听处理Future异步信息的结果:

//处理完成时候的回调,一般都是成功回调
Future<R> then<R>(FutureOr<R> onValue(T value), {Function onError});
//处理失败的回调,比如throw一个error就会走到这里
Future<T> catchError(Function onError, {bool test(Object error)});
//Future.whenComplete总是在Future完成后调用,不管Future的结果是正确的还是错误的。
Future<T> whenComplete(FutureOr action());

Future 的构造方法,创建一个基本的Future

var f1 = Future(() {
  print("1111");
});
print("33233");

//33233
//1111

创建一个指定返回值的Future

Future.value("Success").then((value) => (print('测试$value')));

创建一个延迟执行的 Future

//延迟三秒执行
 Future.delayed(Duration(seconds: 3), () {
   print("future delayed");
 });

根据某个集合,创建一系列的Future,并且会按顺序执行这些Future

Future.forEach([1,2,3], (item) {
    return Future.delayed(Duration(seconds: 2),() {
      print(item);
    });
});

//1
//2
//3

串行执行多个异步任务

var f1 = Future.delayed(Duration(seconds: 1),() => (1));
var f2 = Future.delayed(Duration(seconds: 2),() => (2));
var f3 = Future.delayed(Duration(seconds: 3),() => (3));
Future.wait([f1,f2,f3]).then((value) => print(value)).catchError(print);

在上述创建的异步任务都是添加到event队列中的任务,创建一个在microtask队列运行的future,microtask队列的优先级是比event队列高的。

Future(() => (print(11111)));
Future(() => (print(22222)));
Future.microtask(() => (print(33333)));

公众号 我的大前端生涯

相关文章
|
2月前
|
存储 开发框架 JavaScript
深入探讨Flutter中动态UI构建的原理、方法以及数据驱动视图的实现技巧
【6月更文挑战第11天】Flutter是高效的跨平台移动开发框架,以其热重载、高性能渲染和丰富组件库著称。本文探讨了Flutter中动态UI构建原理与数据驱动视图的实现。动态UI基于Widget树模型,状态变化触发UI更新。状态管理是关键,Flutter提供StatefulWidget、Provider、Redux等方式。使用ListView等可滚动组件和StreamBuilder等流式组件实现数据驱动视图的自动更新。响应式布局确保UI在不同设备上的适应性。Flutter为开发者构建动态、用户友好的界面提供了强大支持。
51 2
|
9天前
|
Dart 前端开发 JavaScript
Flutter&Dart-异步编程Future、Stream极速入门
Flutter&Dart-异步编程Future、Stream极速入门
29 4
Flutter&Dart-异步编程Future、Stream极速入门
|
1月前
|
Dart JavaScript Java
flutter 架构、渲染原理、家族
flutter 架构、渲染原理、家族
43 2
|
2月前
|
移动开发 Dart 前端开发
深度分析:React Native、Flutter、UniApp、Taro、Vue的差异
深度分析:React Native、Flutter、UniApp、Taro、Vue的差异
167 6
|
1月前
|
Dart
flutter 之 Dart 异步编程【详解】
flutter 之 Dart 异步编程【详解】
19 0
|
3月前
|
Android开发
Flutter完整开发实战详解(六、 深入Widget原理),2024百度Android岗面试真题收录解析
Flutter完整开发实战详解(六、 深入Widget原理),2024百度Android岗面试真题收录解析
|
3月前
|
Dart 前端开发 UED
【Flutter前端技术开发专栏】深入理解Flutter中的流(Streams)和异步编程
【4月更文挑战第30天】探索Flutter的异步编程与流:了解异步编程在提升响应性和避免阻塞中的作用,掌握Stream、StreamController和StreamSubscription核心概念。通过实践案例学习如何使用流处理网络请求,提升应用性能。参考Dart和Flutter官方文档,深入理解并运用异步模式,如回调、async/await和Futures,构建更佳用户体验的Flutter应用。
53 0
【Flutter前端技术开发专栏】深入理解Flutter中的流(Streams)和异步编程
|
3月前
|
Dart 前端开发 API
【Flutter前端技术开发专栏】Flutter中的异步编程与Future/async/await
【4月更文挑战第30天】本文探讨了Flutter中的异步编程,强调其在提高应用响应性和性能上的重要性。Flutter使用`Future`对象表示异步操作的结果,通过`.then()`和`.catchError()`处理异步任务。此外,Dart的`async/await`关键字简化了异步代码,使其更易读。理解并运用这些概念对于开发高效的Flutter应用至关重要。
26 0
【Flutter前端技术开发专栏】Flutter中的异步编程与Future/async/await
|
3月前
|
开发框架 前端开发 JavaScript
【专栏】对比分析两种流行的跨平台开发框架——Flutter和React Native,探讨它们的优势、劣势以及适用场景
【4月更文挑战第27天】本文对比分析了Flutter和React Native两大跨平台移动开发框架。Flutter,由Google推出,以其接近原生的性能、快速启动和流畅滚动受青睐,适合高性能和高度定制的项目。React Native,Facebook维护,依赖JavaScript,虽性能受限,但热重载优势和丰富第三方库使其适合快速迭代的项目。两者都在拓展多平台应用,Flutter在桌面和Web,React Native在Windows。选择框架需考虑项目需求、团队技能和性能效率平衡。
299 1
|
3月前
|
开发框架 Dart API
Flutter引擎工作原理:深入解析FlutterEngine
【4月更文挑战第26天】FlutterEngine是Flutter应用的关键,负责Dart代码转换为原生代码,管理应用生命周期、渲染和事件处理。它初始化Flutter运行时环境,加载并编译Dart代码,创建渲染树,处理事件并实现跨平台兼容。通过理解其工作原理,开发者能更好地掌握Flutter应用内部机制并优化开发。随着Flutter生态系统发展,FlutterEngine将持续提供强大支持。