🧱 1. Isolate 是什么?—— “独立的小房间”
- 每个 Isolate 都是独立运行的:就像公司里每个员工有自己的办公室,互不干扰。一个房间卡住了(比如计算太复杂),其他房间照样工作。
- 不共享内存:员工之间不能直接翻对方的文件柜(内存隔离),只能通过“传纸条”(消息传递)沟通。
- 解决卡顿问题:Flutter 的 UI 在主 Isolate(主线程)运行,如果主房间在干重活(如解析大文件),UI 就会卡住。这时把重活扔给另一个 Isolate,UI 就流畅了。
⚙️ 2. 为什么需要 Isolate?—— “不让主线程累趴”
- 主线程负责 UI:所有按钮点击、动画渲染都在主线程跑。
- 耗时任务会阻塞 UI:比如计算 1 亿次加法、读取超大文件、处理图像。这些任务如果在主线程跑,App 就卡成幻灯片。
- Isolate 的用途:把这些耗时任务丢到另一个 Isolate 后台执行,主线程继续流畅响应用户操作。
🛠️ 3. 怎么用 Isolate?—— “两种开小号方式”
(1) 手动创建:Isolate.spawn()
适合复杂任务,需要自己管理消息传递:
import 'dart:isolate';
// 后台任务函数(必须是静态函数或全局函数)
void backgroundTask(SendPort sendPort) {
int result = 0;
for (int i = 0; i < 1000000000; i++) {
result += i; // 模拟耗时计算
}
sendPort.send(result); // 把结果传回主线程
}
void main() async {
ReceivePort receivePort = ReceivePort(); // 主线程的“收件箱”
await Isolate.spawn(backgroundTask, receivePort.sendPort); // 启动新 Isolate
// 监听结果
receivePort.listen((result) {
print("计算结果:$result");
receivePort.close(); // 关闭收件箱
});
}
处理两个任务的代码
import 'dart:async';
import 'dart:isolate';
import 'package:flutter/material.dart';
// 任务1:模拟图像处理(高斯模糊)
Future<String> _processImage(String imagePath) async {
await Future.delayed(const Duration(seconds: 2)); // 模拟耗时
return "处理成功: ${imagePath.split('/').last} (模糊度: 10px)";
}
// 任务2:模拟网络请求(获取用户数据)
Future<String> _fetchUserData(int userId) async {
await Future.delayed(const Duration(seconds: 3)); // 模拟网络延迟
if (userId > 100) throw Exception("用户ID无效");
return "用户数据: {id: $userId, name: '用户$userId'}";
}
// 启动两个 Isolate 并汇总结果
Future<Map<String, dynamic>> runParallelTasks() async {
final ReceivePort resultPort = ReceivePort();
final Completer<Map<String, dynamic>> completer = Completer();
// 错误收集器
final errors = {};
// 任务计数器
int completedCount = 0;
const totalTasks = 2;
resultPort.listen((message) {
if (message is Map) {
final String taskType = message['type'];
if (message.containsKey('result')) {
completer.isCompleted
? null
: completer.complete({...completer.future.then((v) => v) ?? {}, taskType: message['result']});
} else if (message.containsKey('error')) {
errors[taskType] = message['error'];
}
completedCount++;
}
// 所有任务完成(成功或失败)
if (completedCount == totalTasks) {
resultPort.close();
if (errors.isNotEmpty) completer.completeError(errors);
}
});
// 启动图像处理 Isolate
Isolate.spawn(
_isolateTaskHandler,
{
'type': 'image',
'task': () => _processImage('assets/images/photo.jpg'),
'sendPort': resultPort.sendPort,
},
);
// 启动网络请求 Isolate
Isolate.spawn(
_isolateTaskHandler,
{
'type': 'network',
'task': () => _fetchUserData(200), // 此处故意传入错误ID触发异常
'sendPort': resultPort.sendPort,
},
);
return completer.future;
}
// Isolate 任务处理器
void _isolateTaskHandler(Map<String, dynamic> message) async {
final String type = message['type'];
final Function task = message['task'];
final SendPort sendPort = message['sendPort'];
try {
final result = await task();
sendPort.send({'type': type, 'result': result});
} catch (e) {
sendPort.send({'type': type, 'error': e.toString()});
}
}
// 界面组件
class ParallelIsolateDemo extends StatefulWidget {
const ParallelIsolateDemo({super.key});
@override
State<ParallelIsolateDemo> createState() => _ParallelIsolateDemoState();
}
class _ParallelIsolateDemoState extends State<ParallelIsolateDemo> {
Map<String, dynamic>? _results;
String? _error;
void _startTasks() async {
setState(() {
_results = null;
_error = null;
});
try {
final results = await runParallelTasks();
setState(() => _results = results);
} catch (e) {
setState(() => _error = "错误: ${e.toString()}");
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('双任务并行 Isolate')),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
ElevatedButton(
onPressed: _startTasks,
child: const Text('启动双任务'),
),
const SizedBox(height: 20),
if (_results != null) ...[
Text('图像结果: ${_results!['image']}'),
Text('网络结果: ${_results!['network']}'),
],
if (_error != null)
Text(_error!, style: const TextStyle(color: Colors.red)),
],
),
),
);
}
}
// 应用入口
void main() => runApp(
MaterialApp(
home: Scaffold(body: Center(child: ParallelIsolateDemo())),
),
);