Flutter 异步编程:Future 与 Stream 深度解析

系列入口:

1️⃣ Future 与 Stream 深度解析

2️⃣Isolate 与 compute 性能优化

3️⃣ FutureBuilder 与 StreamBuilder 架构优化

4️⃣ 异步 + 状态管理融合(Riverpod / Bloc)

5️⃣ Flutter 响应式架构设计

欢迎留言 👍 点个 关注 ❤️,不错过后续更新!

引言

在 Flutter 开发中,异步编程无处不在------从网络请求到动画控制、文件读写到 Socket 通信。
而支撑这一切的核心机制,就是 Future 与 Stream。

本文将结合项目实战,从原理到最佳实践,一次性搞懂 Flutter 的异步体系。

一、为什么 Flutter 需要异步?

Flutter 采用 单线程 UI 渲染模型

主 Isolate 负责所有渲染与事件响应,如果执行耗时任务(如 I/O 或 JSON 解析)会造成 UI 卡顿。

异步编程的意义:让程序在"等待"的同时继续渲染界面。

Kotlin 复制代码
void fetchData() {
  final data = http.get('https://api.example.com/user');
  print('请求已发送');
}

这时 print 会先执行,因为 Dart 的事件循环会让 Future 异步排队执行。

二、Future:一次性异步任务

Future 表示一个将来会返回结果的异步操作。它可以成功、失败或超时。

Kotlin 复制代码
Future<String> getUserName() async {
  await Future.delayed(const Duration(seconds: 2));
  return 'FlutterDev';
}

void main() async {
  print('开始');
  final name = await getUserName();
  print('你好,$name');
}

输出:

Kotlin 复制代码
开始
(等待2秒)
你好,FlutterDev

三、async / await 实战与最佳实践

1. async + await 原理速记

  • async 把函数变成异步函数,返回 Future<T>

  • await暂停当前函数 直到该 Future 完成;

  • await 后续代码会被放入 microtask 队列,优先执行。

Kotlin 复制代码
Future<User> fetchUser() async {
  final res = await http.get(Uri.parse('https://api.xxx.com/user'));
  return User.fromJson(json.decode(res.body));
}

2. 串行 vs 并行

Kotlin 复制代码
// 串行(前一步结果是后一步输入)
final token = await login();
final profile = await fetchProfile(token);

// 并行(互不依赖)
final result = await Future.wait([apiA(), apiB(), apiC()]);

3. 错误与超时

Kotlin 复制代码
try {
  final data = await fetch();
} on TimeoutException {
  print('请求超时');
} catch (e, st) {
  print('异常: $e');
}

4. 重试与竞速

Kotlin 复制代码
Future<T> retry<T>(Future<T> Function() run, {int max = 3}) async {
  var delay = const Duration(milliseconds: 300);
  for (int i = 0; i < max; i++) {
    try { return await run(); } catch (_) {}
    await Future.delayed(delay);
    delay *= 2; // 指数退避
  }
  return await run();
}

// 竞速:谁先返回用谁
final fastest = await Future.any([pingA(), pingB()]);

5. UI绑定:FutureBuilder

Kotlin 复制代码
FutureBuilder<User>(
  future: fetchUser(),
  builder: (_, snap) {
    if (snap.connectionState == ConnectionState.waiting) {
      return const CircularProgressIndicator();
    }
    if (snap.hasError) return Text('错误:${snap.error}');
    return Text('Hi, ${snap.data!.name}');
  },
);

6. 异步取消

Dart 的 Future 无法直接取消,可用软标志:

Kotlin 复制代码
bool _canceled = false;
Future<void> runJob() async {
  _canceled = false;
  final a = await step1();
  if (_canceled) return;
  final b = await step2(a);
}
void cancelJob() => _canceled = true;

或使用 CancelableOperation(来自 package:async)。

7. 小结口诀

有依赖 → 串行;无依赖 → 并行;

操作UI前先判断 mounted

超时、重试、竞速都靠 Future 组合。

四、Stream:持续事件的流

Stream 用于处理多次异步事件,如进度更新、传感器、Socket。

Kotlin 复制代码
final controller = StreamController<int>();

controller.stream.listen(
  (event) => print('收到:$event'),
  onError: (e) => print('错误:$e'),
  onDone: () => print('结束'),
);

controller.add(1);
controller.add(2);
controller.close();

输出:

收到:1

收到:2

结束

常见应用场景

场景 示例
下载/上传进度 Stream<double>
蓝牙 / 串口数据 Stream<List<int>>
用户输入防抖 debounce
Socket 长连接 Stream<String>

五、Future vs Stream 对比

特性 Future Stream
结果数量 一次 多次
典型场景 网络请求 进度/Socket
取消支持 可取消订阅
UI绑定组件 FutureBuilder StreamBuilder

六、Event Loop 与微任务机制

Dart 异步执行顺序:

microtask → event → render → 下一帧

示例:

Kotlin 复制代码
print('A');
scheduleMicrotask(() => print('B'));
Future(() => print('C'));
print('D');
// 输出: A, D, B, C

七、实战案例:下载进度条

Kotlin 复制代码
class DownloadTask {
  final _ctrl = StreamController<double>();

  Stream<double> get progress => _ctrl.stream;

  Future<void> start() async {
    for (int i = 1; i <= 10; i++) {
      await Future.delayed(const Duration(milliseconds: 500));
      _ctrl.add(i / 10);
    }
    _ctrl.close();
  }
}

final task = DownloadTask();

task.progress.listen((p) => print('进度: ${(p * 100).toInt()}%'));
task.start();

八、异步任务选型决策表

场景 推荐方案
一次性请求(接口 / 文件) Future + async/await
多次更新(进度 / 实时数据) Stream
并发请求 Future.wait / Future.any
可取消任务 CancelableOperation
大计算任务 compute / Isolate
UI绑定 FutureBuilder / StreamBuilder

九、总结

  • Future:一次性异步操作;

  • Stream:多次事件流;

  • async/await:让异步像同步;

  • Event Loop:协调调度顺序;

  • 搭配 FutureBuilderStreamBuilder

    就能构建不卡顿、响应流畅的 Flutter 界面。

相关推荐
JosieBook1 天前
【Vue】05 Vue技术——Vue 数据绑定的两种方式:单向绑定、双向绑定
前端·javascript·vue.js
极客小云1 天前
【深入理解 Android 中的 build.gradle 文件】
android·安卓·安全架构·安全性测试
Juskey iii1 天前
Android Studio Electric Eel | 2022.1.1 Patch 2 版本下载
android·ide·android studio
Android技术之家1 天前
2025年度Android行业总结:AI驱动生态重构,跨端融合开启新篇
android·人工智能·重构
想学后端的前端工程师1 天前
【浏览器工作原理与性能优化指南:深入理解Web性能】
前端·性能优化
洞见前行1 天前
Android第二代加固技术原理详解(附源码)
android
程序员爱钓鱼1 天前
Node.js 编程实战:错误处理与安全防护
前端·后端·node.js
Geoffwo1 天前
Electron 打包后 exe 对应的 asar 解压 / 打包完整流程
前端·javascript·electron
风清云淡_A1 天前
【JetCompose】入门教程实战基础案例01之显隐动画
android
柒@宝儿姐1 天前
vue3中使用element-plus的el-scrollbar实现自动滚动(横向/纵横滚动)
前端·javascript·vue.js