Skip to content

并发编程

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');
}

方案选择

场景推荐方案
一次性耗时计算computeIsolate.run
JSON / 数据解析compute
需要进度回调的长时间任务Isolate.spawn + SendPort
需要取消任务Isolate.spawn + isolate.kill()
I/O 操作async/await(不需要 Isolate)

核心原则

  1. I/O 操作用 async/await —— 不占 CPU,不需要 Isolate
  2. CPU 密集型任务用 Isolate —— 避免 UI 卡顿
  3. 简单场景用 compute —— 代码最少,自动管理
  4. 复杂场景用 Isolate.spawn —— 双向通信、任务取消等

下一步

基于 Flutter 官方文档整理