并发编程
Dart 是单线程语言,所有代码默认运行在主 Isolate 中。当遇到耗时计算时,如果直接在主 Isolate 中执行,会导致 UI 卡顿。Isolate 是 Dart 提供的并发方案,可以让耗时任务在独立线程中运行,不阻塞 UI。
Isolate 是什么?
Isolate 可以理解为 Dart 中的"线程",但它与操作系统线程有重要区别:
| 特性 | Isolate | 操作系统线程 |
|---|---|---|
| 内存 | 各自独立,不共享内存 | 共享内存 |
| 通信 | 通过消息传递(SendPort / ReceivePort) | 通过共享内存 |
| 锁 | 不需要锁 | 需要加锁防止竞态 |
| 开销 | 比线程轻量 | 较重 |
核心概念
Isolate 之间不共享内存,只能通过 SendPort / ReceivePort 传递消息。这是 Isolate 与线程最大的区别,也是它不需要锁的原因。
何时需要 Isolate?
需要 Isolate 的场景
- 解析大型 JSON(如几 MB 的配置文件)
- 图片处理(压缩、裁剪、滤镜)
- 加密 / 解密操作
- 大量数学计算(排序、搜索)
- 文件读写(大文件)
不需要 Isolate 的场景
- 网络请求 ——
http/dio内部已异步处理,不阻塞 UI - 简单的数据转换 ——
json.decode小数据量很快 - 读写 SharedPreferences —— 数据量小,速度够快
如何判断?
如果耗时操作超过 16 毫秒(一帧的时间),就可能影响 UI 流畅度,应考虑使用 Isolate。
compute — 简化版 Isolate
Flutter 提供了 compute 函数,它是 Isolate.spawn 的高层封装,使用最简单。
dart
import 'package:flutter/foundation.dart';
// 耗时函数(必须是顶层函数或静态方法)
int heavyCalculation(int limit) {
int sum = 0;
for (int i = 0; i < limit; i++) {
sum += i;
}
return sum;
}
Future<void> main() async {
// compute(函数, 参数) —— 一步到位
// ─── ★ compute 简化版 Isolate ──────────────
final result = await compute(heavyCalculation, 100000000);
// ─── ☆ compute 简化版 Isolate ──────────────
print('计算结果: $result');
}在 Widget 中使用 compute
dart
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
class SortPage extends StatefulWidget {
const SortPage({super.key});
@override
State<SortPage> createState() => _SortPageState();
}
class _SortPageState extends State<SortPage> {
bool _isSorting = false;
String _result = '';
Future<void> _sortData() async {
setState(() => _isSorting = true);
final rawData = List.generate(1000000, (i) => (i * 7 + 13) % 1000000);
// 使用 compute 在子 Isolate 中排序
// ─── ★ Widget 中使用 compute ──────────────
final sorted = await compute(_sortList, rawData);
// ─── ☆ Widget 中使用 compute ──────────────
// ─── ★ 异步操作后检查 mounted ──────────────
if (!mounted) return;
// ─── ☆ 异步操作后检查 mounted ──────────────
setState(() {
_isSorting = false;
_result = '排序完成,共 ${sorted.length} 条数据';
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Isolate 排序')),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
if (_result.isNotEmpty)
Text(_result, style: const TextStyle(fontSize: 16)),
const SizedBox(height: 16),
ElevatedButton(
onPressed: _isSorting ? null : _sortData,
child: _isSorting
? const SizedBox(
width: 20,
height: 20,
child: CircularProgressIndicator(strokeWidth: 2),
)
: const Text('排序 100 万条数据'),
),
],
),
),
);
}
}
// 顶层函数(compute 要求必须是顶层函数或静态方法)
List<int> _sortList(List<int> data) {
data.sort();
return data;
}Isolate.spawn — 完整版 Isolate
需要双向通信或多次交互时,使用 Isolate.spawn。
dart
import 'dart:isolate';
void heavyTask(SendPort sendPort) {
int result = 0;
for (int i = 0; i < 100000000; i++) {
result += i;
}
sendPort.send(result); // 通过 SendPort 发送结果
}
Future<void> main() async {
final receivePort = ReceivePort();
await Isolate.spawn(heavyTask, receivePort.sendPort);
receivePort.listen((message) {
print('计算结果: $message');
receivePort.close();
});
}双向通信
dart
void worker(SendPort mainSendPort) {
final workerReceivePort = ReceivePort();
mainSendPort.send(workerReceivePort.sendPort);
workerReceivePort.listen((message) {
if (message == 'start') {
final result = doHeavyWork();
mainSendPort.send(result);
}
});
}Isolate.run — 线程池版
Dart 2.19 引入了 Isolate.run,使用系统管理的 Isolate 线程池,性能更好:
dart
import 'dart:isolate';
Future<void> main() async {
final result = await Isolate.run(() {
// 支持闭包
int sum = 0;
for (int i = 0; i < 100000000; i++) {
sum += i;
}
return sum;
});
print('结果: $result');
}方案选择
| 场景 | 推荐方案 |
|---|---|
| 一次性耗时计算 | compute 或 Isolate.run |
| JSON / 数据解析 | compute |
| 需要进度回调的长时间任务 | Isolate.spawn + SendPort |
| 需要取消任务 | Isolate.spawn + isolate.kill() |
| I/O 操作 | async/await(不需要 Isolate) |
核心原则
- I/O 操作用 async/await —— 不占 CPU,不需要 Isolate
- CPU 密集型任务用 Isolate —— 避免 UI 卡顿
- 简单场景用 compute —— 代码最少,自动管理
- 复杂场景用 Isolate.spawn —— 双向通信、任务取消等
下一步
- 平台差异处理 — 判断平台 / 条件渲染
