在 Flutter 和 Dart 里,由于单线程执行模型的存在,若要实现多线程操作,需借助Isolate。
使用 compute 函数(适用于简单场景)
compute函数能够把耗时任务放到后台 Isolate 中执行,特别适合处理简单的计算任务。
- 自动管理 Isolate:无需手动创建和销毁 Isolate,系统会自动处理。
- 简化数据传递:借助函数参数和返回值实现数据传递,无需手动管理SendPort。
- 类型安全:支持泛型,确保输入输出类型的一致性。
- 必须是顶级或静态函数:回调函数(如上述示例中的isPrime)必须是顶级函数或者类的静态方法,这是因为 Isolate 需要独立于 UI 线程运行。
- 自动错误处理:如果后台任务抛出异常,compute会将异常传递给调用方,可通过try-catch捕获。
- 适用于简单任务:适合执行单次的计算任务,例如 JSON 解析、图片处理、数学运算等。
- 数据传递限制:参数和返回值必须是可序列化的对象(如基本数据类型、列表、映射等)。
import 'package:flutter/foundation.dart';
import 'dart:math';
// 顶级函数:判断素数(耗时操作)
bool isPrime(int number) {
if (number <= 1) return false;
for (int i = 2; i <= sqrt(number); i++) {
if (number % i == 0) return false;
}
return true;
}
class PrimeChecker extends StatefulWidget {
@override
_PrimeCheckerState createState() => _PrimeCheckerState();
}
class _PrimeCheckerState extends State<PrimeChecker> {
bool? _isPrime;
bool _isLoading = false;
Future<void> _checkPrime(int number) async {
setState(() => _isLoading = true);
// 在后台Isolate执行计算
final result = await compute(isPrime, number);
setState(() {
_isPrime = result;
_isLoading = false;
});
}
@override
Widget build(BuildContext context) {
return Column(
children: [
ElevatedButton(
onPressed: () => _checkPrime(123456789),
child: Text('检查是否为素数'),
),
if (_isLoading) CircularProgressIndicator()
else if (_isPrime != null)
Text('$(_isPrime! ? '是' : '不是') 素数'),
],
);
}
}
2. 使用Isolate.run()
简化语法,适合快速执行独立任务。
void main() async {
final result = await Isolate.run(() {
// 耗时操作(自动在新Isolate中执行)
return heavyTask();
});
print('异步结果: $result');
}
int heavyTask() {
// 模拟耗时计算
return 42;
}
3. 手动创建 Isolate(完整版)
适用于复杂场景,需手动管理生命周期和通信。
import 'dart:isolate';
void main() async {
// 1. 创建接收端口(用于接收消息)
final receivePort = ReceivePort();
// 2. 启动新Isolate,传入入口函数和发送端口
final isolate = await Isolate.spawn(
workerFunction, // 入口函数(必须是顶级或静态方法)
receivePort.sendPort, // 发送端口,用于传递消息
);
// 3. 监听消息
receivePort.listen((message) {
print('收到消息: $message');
// 任务完成后销毁Isolate
isolate.kill(priority: Isolate.immediate);
receivePort.close();
});
}
// 新Isolate的入口函数
void workerFunction(SendPort sendPort) {
// 执行耗时操作
int result = 0;
for (int i = 0; i < 1000000; i++) {
result += i;
}
// 发送结果回主Isolate
sendPort.send('计算结果: $result');
}
使用例子
文件处理(如大文件解析)
使用手动 Isolate 解析大型 JSON 文件:
import 'dart:io';
import 'dart:isolate';
import 'dart:convert';
void main() async {
final receivePort = ReceivePort();
await Isolate.spawn(
parseJsonFile,
{'path': 'large_file.json', 'sendPort': receivePort.sendPort},
);
receivePort.listen((data) {
print('解析完成,数据长度: ${data.length}');
receivePort.close();
});
}
// 新Isolate中执行文件解析
void parseJsonFile(dynamic message) {
final String path = message['path'];
final SendPort sendPort = message['sendPort'];
try {
final file = File(path);
final jsonString = file.readAsStringSync();
final parsedData = json.decode(jsonString);
sendPort.send(parsedData);
} catch (e) {
sendPort.send(null);
}
}
图像处理(如滤镜应用)
在后台线程处理图像数据:
import 'dart:ui' as ui;
import 'package:flutter/foundation.dart';
// 应用灰度滤镜(耗时操作)
Future<ui.Image> applyGrayscale(ui.Image image) async {
return await compute(_processImage, image);
}
// 必须是顶级函数
ui.Image _processImage(ui.Image image) {
// 创建图像处理器
final completer = Completer<ui.Image>();
// 获取图像数据
image.toByteData(format: ui.ImageByteFormat.rawRgba).then((byteData) {
if (byteData == null) return;
final buffer = byteData.buffer;
final length = buffer.lengthInBytes;
// 应用灰度滤镜(修改每个像素)
for (int i = 0; i < length; i += 4) {
final r = buffer.asUint8List()[i];
final g = buffer.asUint8List()[i + 1];
final b = buffer.asUint8List()[i + 2];
// 计算灰度值
final gray = (r * 0.299 + g * 0.587 + b * 0.114).toInt();
// 应用到RGB通道
buffer.asUint8List()[i] = gray;
buffer.asUint8List()[i + 1] = gray;
buffer.asUint8List()[i + 2] = gray;
}
// 创建处理后的图像
ui.decodeImageFromPixels(
buffer.asUint8List(),
image.width,
image.height,
ui.PixelFormat.rgba8888,
(processedImage) => completer.complete(processedImage),
);
});
return completer.future;
}
持续后台任务(如进度监控)
使用手动 Isolate 实现进度监控:
import 'dart:isolate';
class ProgressMonitor {
late Isolate _isolate;
final ReceivePort _receivePort = ReceivePort();
final void Function(double progress) onProgress;
ProgressMonitor({required this.onProgress});
Future<void> start() async {
_isolate = await Isolate.spawn(
_monitorProgress,
_receivePort.sendPort,
);
_receivePort.listen((message) {
if (message is double) {
onProgress(message);
}
});
}
void stop() {
_isolate.kill();
_receivePort.close();
}
// 独立Isolate中运行的进度监控
static void _monitorProgress(SendPort sendPort) {
double progress = 0.0;
while (progress < 1.0) {
// 模拟进度更新
progress += 0.01;
sendPort.send(progress);
sleep(Duration(milliseconds: 100));
}
}
}