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 界面。

相关推荐
Kisang.3 分钟前
【HarmonyOS】ArkWeb——从入门到入土
前端·华为·typescript·harmonyos·鸿蒙
沉默璇年9 分钟前
tgz包批量下载脚本
前端
a***131430 分钟前
python的sql解析库-sqlparse
android·前端·后端
r***869835 分钟前
mysql的主从配置
android·mysql·adb
.豆鲨包37 分钟前
【Android】深入理解Activity的生命周期和IntentFilter
android·java
啃火龙果的兔子41 分钟前
安卓从零开始
android
CryptoRzz42 分钟前
印度股票数据 PHP 对接文档 覆盖 BSE(孟买证券交易所)和 NSE(印度国家证券交易所)的实时数据
android·服务器·开发语言·区块链·php
0***R5151 小时前
前端构建工具缓存,node_modules
前端·缓存
坚持就完事了1 小时前
CSS-4:CSS的三大特性
前端·css
坚持就完事了1 小时前
CSS-3:背景设置
前端·css·html