【Flutter】Flutter 异步方法调用 ( async 和 await 关键字解析 | Dart 单线程 | await 调用方式对比 | Future<void> 返回值作用 )
·
文章目录
一、错误记录
编译 Flutter 应用时 , 报如下错误 :
D:\002_Project\001_Flutter\client_terminal>flutter build apk --debug
Flutter assets will be downloaded from https://storage.flutter-io.cn. Make sure you trust this source!
Flutter assets will be downloaded from https://storage.flutter-io.cn. Make sure you trust this source!
lib/pages/login_page.dart:38:5: Error: 'await' can only be used in 'async' or 'async*' methods.
await LoginController().login(context, _accountController.text, _passwordController.text); // 调用登录方法 , 传入账号和密码
^^^^^
Target kernel_snapshot_program failed: Exception
FAILURE: Build failed with an exception.
* What went wrong:
Execution failed for task ':app:compileFlutterBuildDebug'.
> Process 'command 'D:\001_Develop\026_Flutter_3.41.7\flutter\bin\flutter.bat'' finished with non-zero exit value 1
* Try:
> Run with --stacktrace option to get the stack trace.
> Run with --info or --debug option to get more log output.
> Run with --scan to get full insights.
> Get more help at https://help.gradle.org.
BUILD FAILED in 10s
Running Gradle task 'assembleDebug'... 10.7s
Gradle task assembleDebug failed with exit code 1
D:\002_Project\001_Flutter\client_terminal>

二、原理分析
1、报错分析
报错问题 :
Error: 'await' can only be used in 'async' or 'async*' methods.
报错原因是 在一个「普通方法 / 按钮点击」里写了 await , 但这个方法 没有加 async 关键字 ;
await 必须配合 async 一起用 , 否则 Dart 直接报错 ;
- async 是 " 声明这是一个异步方法 " ;
- await 是 " 等待这个异步任务执行完 " ;
- await 只能在 async 方法里用 , 否则报错 ;
2、async 和 await 关键字解析
Dart 是单线程语言 , 不能真正阻塞 , 所以用 异步 + 事件循环 实现不卡顿 ;
- async 关键字 : 把方法包装成异步任务 ;
- await 关键字 : 暂停当前方法 , 不阻塞主线程 , 等任务完成后再恢复执行 ;
表面看像同步代码 , 底层实际是异步非阻塞执行 ;
async 关键字 作用 : 告诉 Dart 这个方法里面有异步操作 , 不能立刻执行完 ;
- 加了 async , 方法就变成异步方法
- 异步方法自动返回 Future
- 只有加了它 , 里面才能写 await
await 关键字 作用 : 等待后面的异步任务执行完成 , 再继续往下走 ;
- 等待网络请求
- 等待文件读写
- 等待数据库操作
- 等待延时
3、Dart 单线程
Dart 永远是单线程 , 不会卡住 , 但它有一个机制 :
- 遇到耗时操作 ( await ) , 就先挂起 , 去干别的事
- 耗时操作做完 , 再回来继续执行
- 它不会阻塞线程 , 但可以 " 等待任务结果 " ;
两个写法都是单线程 , 但执行结果完全不一样 ;
await doSomething();→ 会等待 , 等里面的异步任务 ( 网络请求 / 延时 ) 真正做完 , 才继续往下走 ;doSomething();→ 不会等待 , 直接立刻往下执行 , 异步任务在后台自己慢慢跑 ;
4、await 调用方式对比
调用下面的方法 :
Future<void> doSomething() async {
await Future.delayed(Duration(seconds: 2)); // 模拟耗时2秒
print("任务完成");
}
使用 await 关键字调用
使用
print("开始");
await doSomething(); // 等待2秒
print("结束");
方式 , 进行调用 , 得到的结果 :
开始
( 等待2秒 )
任务完成
结束
不使用 await 关键字调用
使用
print("开始");
doSomething(); // 不等待 , 直接跳过
print("结束");
方式执行 , 结果
开始
结束
( 2秒后 )
任务完成
5、Future<void> 返回值作用
Future<void> 这个返回值的真正作用 = 让外部能「等待」这个方法执行完 ;
- 没有它 , 你就不能用 await ;
- 不能用 await , 你就无法控制执行顺序 ;
Future<void>不是 " 返回内容 " , 而是一个「任务凭证 / 任务小票」 ;
- void = 没有实际数据返回 ( 不 return 任何值 ) ;
- Future = 代表一个异步任务 , 可以被等待 ;
await 只能等待 Future 返回值类型的函数 :
- 你给它 void → 它不认识 , 无法等待 ;
- 你给它 Future → 它认识 , 可以等待 ;
三、解决方案
1、方案 1 : 方法加上 async
方案 1 : 给方法加上 async ( 最常用、最标准 )
Future<void> _handleLogin() async {
await LoginController().login(username, password);
}
2、方案 2 : 调用去掉 await
方案 2 : 如果不需要等待 , 直接去掉 await ;
void _handleLogin() {
LoginController().login(username, password);
}
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐
所有评论(0)