Flutter 中的 async/await 和 Future

06-02 1118阅读

含义

在 Flutter/Dart 中,Future 和 async/await 是处理异步操作的核心机制。以下是它们的极简说明:


1. Future

  • 是什么:表示一个异步操作的 未来结果(可能未完成)
  • 典型场景:网络请求、文件读写、数据库操作等耗时任务
    Future fetchData() {
      return Future.delayed(Duration(seconds: 2), () => "数据加载完成");
    }
    

    2. async / await

    • 作用:以同步代码风格写异步逻辑,避免回调地狱
    • 规则:
      • async 标记异步函数
      • await 等待 Future 完成并返回实际结果
        void loadData() async {
          String data = await fetchData(); // 等待Future完成
          print(data); // 输出: "数据加载完成"
        }
        

        核心关系

        关键词角色示例
        Future异步任务的"欠条"Future number
        async标记函数内有异步操作func() async {...}
        await暂停执行直到Future完成var x = await future

        注意事项

        1. await 必须在 async 函数内使用
        2. 被 await 修饰的代码会顺序执行
        3. 未处理的异常需要用 try/catch 捕获

        比喻理解:

        Future 像外卖订单,async/await 是你在家等着外卖送到再开门(而不是反复打电话问到哪了)。

        好的!我将基于 async/await 和 Future 的特性,为你编写一个 明确展示异步执行顺序 的示例代码。这个示例会清晰体现:

        1. 遇到 await 时暂停等待(当前异步任务)
        2. 不相关的代码继续执行(不阻塞主线程)

        🎯 示例代码

        import 'dart:async';
        // 示例1: 模拟耗时2秒的网络请求
        Future fetchUserData() async {
          await Future.delayed(Duration(seconds: 2)); // 模拟延迟
          return "用户数据: 张三";
        }
        // 示例2: 模拟耗时1秒的本地计算
        Future calculateScore() async {
          await Future.delayed(Duration(seconds: 5)); // 模拟延迟
          return 95;
        }
        void main() async {
          print("程序开始执行");
          // 情景1: 需要等待的结果(用await)
          print("\n--- 开始请求用户数据(需等待结果)---");
          String userData = await fetchUserData(); // 会阻塞当前async函数内的后续代码
          print("收到结果: $userData"); // 2秒后执行
          // 情景2: 不等待的结果(直接执行后续代码)
          print("\n--- 启动分数计算(不等待)---");
          Future futureScore = calculateScore(); // 不写await,直接返回Future对象
          print("此处立即执行,无需等待计算完成");
          // 打印其他无关操作
          print("\n--- 其他操作 ---");
          print("1. 播放背景音乐");
          print("2. 更新UI界面");
          // 事后获取分数结果(通过then回调)
          futureScore.then((score) => print("\n异步计算完成后输出分数: $score"));
        }
        

        📊 执行顺序解析

        时间线输出内容说明
        立即程序开始执行main() 同步代码第一步
        立即--- 开始请求用户数据...---进入需要 await 的异步任务
        2秒后收到结果: 用户数据: 张三fetchUserData() 完成,继续执行后续
        立即--- 启动分数计算...---不写 await,直接返回 Future
        立即此处立即执行...不阻塞,继续执行
        立即--- 其他操作 --- + 两行输出主线程自由执行其他任务
        1秒后异步计算完成后输出分数: 95calculateScore() 完成后通过 then 触发

        🔑 关键结论

        1. 使用 await:会暂停当前 async 函数内的代码执行,直到 Future 完成。

          var result = await someFuture(); // 等待执行完毕
          
        2. 不用 await:立即返回 Future 对象,不阻塞后续代码,通过 .then() 或后续 await 获取结果。

          someFuture().then((result) { ... }); // 回调模式
          
        3. 主线程自由:与当前 async 函数无关的代码(如示例中的播放音乐)始终不受影响。


        🌰 现实场景类比

        • 点外卖(用 await):你在家等外卖到了才吃饭(阻塞后续动作)。
        • 洗衣服(不用 await):启动洗衣机后直接去刷手机(不阻塞),洗完时手机提醒(.then)。

          总结

          如果一个函数返回 Future,你必须通过以下两种方式之一处理它:

          ✅ 方式1:await 等待(同步风格)

          Future fetchData() async {
            await Future.delayed(Duration(seconds: 1));
            return "数据";
          }
          void main() async {
            String data = await fetchData(); // 等待Future完成
            print(data); // 输出: "数据"
          }
          

          特点:

          • 会暂停当前 async 函数,直到 Future 完成
          • 代码按顺序执行,类似同步代码

            ✅ 方式2:.then() 回调(异步风格)

            void main() {
              fetchData().then((data) { // 不阻塞,完成后触发回调
                print(data); // 输出: "数据"
              });
              print("这句会先执行"); // 立即执行,不等待Future
            }
            

            特点:

            • 不阻塞后续代码,Future 完成后自动触发回调
            • 适合不需要立刻结果的场景

              ❗ 必须二选一的原因

              Dart/Flutter 中返回 Future 的函数 本质上是一个异步任务,如果你既不 await 也不 then:

              void main() {
                fetchData(); // ❌ 错误用法!结果会被丢弃(静默忽略)
              }
              
              • 后果:程序不会报错,但你无法获取结果,且无法感知任务是否完成/失败
              • 解决方法:通过 await 或 then 明确处理

                🏆 如何选择?

                场景推荐方式例子
                需要等待结果再继续await登录后跳转页面
                结果可后续处理.then()上传文件后提示成功
                并行多个任务Future.wait同时加载图片和用户数据

                🔥 终极对比表

                特性await.then()
                代码风格同步顺序回调嵌套
                是否会阻塞阻塞当前async函数不阻塞
                异常处理用 try/catch用 .catchError()
                适用场景强依赖结果的流程后台任务/通知

                🌰 简单场景演示

                // 组合使用:先await必要数据,再fire-and-forget其他任务
                void loadPage() async {
                  // 必须等待用户信息
                  var user = await fetchUser(); 
                  print("用户: ${user.name}");
                  // 不等待日志上报
                  uploadLog(user.id).then((_) => print("日志上报成功"));
                  // 继续其他操作
                  print("页面加载完成"); 
                }
                

                总结:

                👉 await = “这个结果我现在就要!”

                👉 .then() = “完成后告诉我,我先忙别的”

                记得永远不要让 Future 变成"孤儿"(既不 await 也不 then)!

免责声明:我们致力于保护作者版权,注重分享,被刊用文章因无法核实真实出处,未能及时与作者取得联系,或有版权异议的,请联系管理员,我们会立即处理! 部分文章是来自自研大数据AI进行生成,内容摘自(百度百科,百度知道,头条百科,中国民法典,刑法,牛津词典,新华词典,汉语词典,国家院校,科普平台)等数据,内容仅供学习参考,不准确地方联系删除处理! 图片声明:本站部分配图来自人工智能系统AI生成,觅知网授权图片,PxHere摄影无版权图库和百度,360,搜狗等多加搜索引擎自动关键词搜索配图,如有侵权的图片,请第一时间联系我们。

目录[+]

取消
微信二维码
微信二维码
支付宝二维码