Ответ
Изоляты в Dart — это модель параллелизма, основанная на передаче сообщений. Каждый изолят имеет свою собственную память и event loop, что позволяет выполнять тяжелые вычисления, не блокируя основной поток UI.
Основные подходы:
-
Функция
compute(для разовых задач): Идеально подходит для вызова чистой функции с тяжелыми вычислениями.import 'package:flutter/foundation.dart'; // Функция ДОЛЖНА быть top-level или static. int _heavyComputation(int input) { // Имитация долгого вычисления (например, обработка изображения). int result = 0; for (int i = 0; i < input * 1000000; i++) { result += i.isEven ? 1 : -1; } return result; } // Вызов в коде UI void onButtonPressed() async { final result = await compute(_heavyComputation, 100); print('Result from isolate: $result'); } -
Низкоуровневый API с
Isolate.spawn(для долгоживущих задач): Используется, когда нужно поддерживать постоянный канал связи.import 'dart:isolate'; // Сообщение для изолята class IsolateMessage { final SendPort sendPort; // Для ответа final int data; IsolateMessage(this.sendPort, this.data); } // Функция, запускаемая в изоляте static void _isolateEntryPoint(IsolateMessage initialMessage) async { final port = ReceivePort(); initialMessage.sendPort.send(port.sendPort); // Отправляем обратный порт await for (final message in port) { if (message is int) { final result = message * 2; initialMessage.sendPort.send(result); // Отправляем результат } } } // Запуск изолята в основном коде Future<void> startLongRunningIsolate() async { final mainReceivePort = ReceivePort(); await Isolate.spawn( _isolateEntryPoint, IsolateMessage(mainReceivePort.sendPort, 0), ); // Получаем sendPort от изолята для дальнейшей связи final isolateSendPort = await mainReceivePort.first as SendPort; isolateSendPort.send(21); // Отправляем задание mainReceivePort.listen((message) { print('Received from isolate: $message'); // 42 }); }
Критически важные ограничения и практика:
- Нет общей памяти: Данные передаются через копирование (для примитивов,
List,Map,Set) или сериализацию. Объекты ваших классов должны реализовыватьfromJson/toJson. - Только top-level или static функции: Функция, передаваемая в
Isolate.spawn, не может быть методом экземпляра или использовать замыкания. - Пакет
isolateдля удобства: Для более удобной работы с передачей сложных сообщений и управления жизненным циклом можно использовать пакеты, такие какflutter_isolate(для Flutter) илиisolate. - Альтернативы: Для задач, связанных с вводом-выводом (сеть, файлы), часто достаточно использовать
async/await, так как они не блокируют поток. Изоляты нужны именно для CPU-интенсивных операций.