- 作者:老汪软件技巧
- 发表时间:2024-08-31 10:02
- 浏览量:
众所周知,在 Flutter 中,await 是用来等待异步操作完成的关键字。它不会阻塞主线程,而是通过 Dart 的事件循环和 Future 对象的机制来实现异步代码的暂停与恢复。
当我们在使用await时候通常需要在函数名后面添加async关键字做标记,那么添加了aysnc后,flutter编译器或者说是flutter运行时做了些什么事情呢?
程序在 await 的异步操作完成后,会回到原先暂停的代码处并继续执行,那么flutter是如何保存这个代码恢复节点的?
带着这两个问题,我们寻找一下答案:
在 Flutter(和 Dart)中,当代码执行到 await 时,程序会暂停当前异步函数的执行,等待 Future 完成,然后在完成后继续执行。为了实现这种行为,Dart 语言使用了一种称为“状态机”(state machine)的机制来记录和管理代码执行的暂停点和恢复点。
状态机的工作原理
异步函数的转换:
状态保存:
事件循环与恢复执行:
恢复执行:
例子:状态机如何处理异步函数
考虑一个简单的异步函数:
Future<void> exampleFunction() async {
print('Start');
await Future.delayed(Duration(seconds: 2));
print('End');
}
当 Dart 编译器看到这个函数时,它会将其转换为类似下面的状态机代码(伪代码):
class _ExampleFunctionStateMachine {
int _state = 0;//默认状态为0
Future<void> run() async {
switch (_state) {
case 0:
print('Start');
_state = 1;//将状态修改为1
return Future.delayed(Duration(seconds: 2)).then((_) => run());//执行完异步任务后重新调用run方法
case 1:
print('End');
return Future.value();
}
}
}
在这个转换后的代码中:
编译时和运行时
将异步函数转换为状态机的过程是在 编译时 完成的,而不是在运行时。具体来说,当你编写一个使用 async/await 的 Dart 函数时,Dart 编译器在编译代码时会将该函数转换为一个状态机,这样在运行时可以管理异步操作的暂停和恢复。
编译时的状态机转换运行时的执行优势总结
Dart 使用状态机来管理异步函数的暂停和恢复。await 触发状态机记录当前执行状态,并在异步操作完成后恢复执行。这个机制确保了异步函数的执行看起来是顺序的,但实际上是通过非阻塞的方式在不同的状态间切换。状态机记录了每个暂停点(代码节点),并在异步操作完成后恢复执行原来的代码。
将异步函数转换为状态机的过程是在编译时完成的。编译器在编译过程中会分析和转换这些函数,使得在运行时,代码可以通过状态机来有效地管理异步操作的暂停和恢复。这种编译时的转换提高了代码的执行效率,同时让开发者的代码保持简单和易读。
尽管 Dart 官方文档没有直接使用“状态机”这一术语,但该术语可以帮助理解编译器和虚拟机如何处理异步操作的机制dart.dev/libraries/a…