Flutter基础(Isolate)
🧱 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);}});// 启动图像处理 IsolateIsolate.spawn(_isolateTaskHandler,{'type': 'image','task': () => _processImage('assets/images/photo.jpg'),'sendPort': resultPort.sendPort,},);// 启动网络请求 IsolateIsolate.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});@overrideState<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()}");}}@overrideWidget 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())),),);