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

公众号 我的大前端生涯

相关文章
|
27天前
|
开发框架 前端开发 Android开发
Flutter 与原生模块(Android 和 iOS)之间的通信机制,包括方法调用、事件传递等,分析了通信的必要性、主要方式、数据传递、性能优化及错误处理,并通过实际案例展示了其应用效果,展望了未来的发展趋势
本文深入探讨了 Flutter 与原生模块(Android 和 iOS)之间的通信机制,包括方法调用、事件传递等,分析了通信的必要性、主要方式、数据传递、性能优化及错误处理,并通过实际案例展示了其应用效果,展望了未来的发展趋势。这对于实现高效的跨平台移动应用开发具有重要指导意义。
105 4
|
27天前
|
缓存 监控 前端开发
优化 Flutter 应用启动速度的策略,涵盖理解启动过程、资源加载优化、减少初始化工作、界面布局优化、异步初始化、预加载关键数据、性能监控与分析等方面
本文探讨了优化 Flutter 应用启动速度的策略,涵盖理解启动过程、资源加载优化、减少初始化工作、界面布局优化、异步初始化、预加载关键数据、性能监控与分析等方面,并通过案例分析展示了具体措施和效果,强调了持续优化的重要性及未来优化方向。
54 10
|
2月前
|
前端开发 JavaScript Android开发
Flutter 与 React Native - 详细深入对比分析(2024 年)
Flutter和React Native是两大跨平台框架,各有优缺点。Flutter性能优越,UI灵活,使用Dart;React Native生态广泛,适合JavaScript开发。
676 5
Flutter 与 React Native - 详细深入对比分析(2024 年)
|
1月前
|
开发者 容器
Flutter&鸿蒙next 布局架构原理详解
本文详细介绍了 Flutter 中的主要布局方式,包括 Row、Column、Stack、Container、ListView 和 GridView 等布局组件的架构原理及使用场景。通过了解这些布局 Widget 的基本概念、关键属性和布局原理,开发者可以更高效地构建复杂的用户界面。此外,文章还提供了布局优化技巧,帮助提升应用性能。
103 4
|
1月前
|
存储 Dart 前端开发
flutter鸿蒙版本mvvm架构思想原理
在Flutter中实现MVVM架构,旨在将UI与业务逻辑分离,提升代码可维护性和可读性。本文介绍了MVVM的整体架构,包括Model、View和ViewModel的职责,以及各文件的详细实现。通过`main.dart`、`CounterViewModel.dart`、`MyHomePage.dart`和`Model.dart`的具体代码,展示了如何使用Provider进行状态管理,实现数据绑定和响应式设计。MVVM架构的分离关注点、数据绑定和可维护性特点,使得开发更加高效和整洁。
163 3
|
2月前
动画控制器在 Flutter 中的工作原理
【10月更文挑战第18天】总的来说,动画控制器 `AnimationController` 在 Flutter 中起着关键的作用,它通过控制动画的数值、速度、节奏和状态,实现了丰富多彩的动画效果。理解它的工作原理对于我们在 Flutter 中创建各种精彩的动画是非常重要的。
|
2月前
|
容器
Flutter&鸿蒙next 布局架构原理详解
Flutter&鸿蒙next 布局架构原理详解
|
1月前
|
缓存 JavaScript API
Flutter&鸿蒙next 状态管理框架对比分析
在 Flutter 开发中,状态管理至关重要,直接影响应用的性能和可维护性。本文对比分析了常见的状态管理框架,包括 setState()、InheritedWidget、Provider、Riverpod、Bloc 和 GetX,详细介绍了它们的优缺点及适用场景,并提供了 Provider 的示例代码。选择合适的状态管理框架需考虑应用复杂度、团队熟悉程度和性能要求。
109 0
|
2月前
|
机器学习/深度学习 开发框架 Dart
Flutter asynchronous 异步编程技巧
本文深入探讨了Flutter中的异步编程技巧,包括Future、Microtask及并发处理的最佳实践。文章详细讲解了Future.wait、FutureBuilder和Microtask的应用,帮助开发者提升应用性能。通过实例演示了如何利用Future.wait实现并发执行,FutureBuilder简化UI构建,以及Microtask的高优先级执行特性。适合希望优化Flutter应用异步性能的开发者阅读。
|
4月前
|
Dart 前端开发 JavaScript
Flutter&Dart-异步编程Future、Stream极速入门
Flutter&Dart-异步编程Future、Stream极速入门
89 4
Flutter&Dart-异步编程Future、Stream极速入门