Какие типы данных можно передавать в изолят?
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Типы данных, которые можно передавать в изолят
Изолят в Dart — это независимый поток выполнения, который работает в отдельной памяти. Это требует особого внимания к тому, какие данные можно туда передавать, так как изоляты не могут напрямую делиться ссылками на объекты.
Типы данных для передачи в изолят
1. Примитивные типы
Все базовые типы данных передаются без проблем:
int number = 42;
double fraction = 3.14;
bool flag = true;
String text = "Hello";
Null nullValue = null;
// Отправить в изолят
isolate.send(number);
isolate.send(text);
Эти типы простые и не требуют копирования сложных структур.
2. Коллекции (List, Map, Set)
Коллекции передаются, но с ограничениями. Элементы коллекции должны быть sendable (передаваемыми):
List<int> numbers = [1, 2, 3];
Map<String, int> data = {'a': 1, 'b': 2};
Set<String> tags = {'flutter', 'dart'};
isolate.send(numbers); // OK
isolate.send(data); // OK если ключи и значения sendable
3. Простые классы (Plain Old Dart Objects)
Простые классы с примитивными полями работают, но нужно учитывать ограничения:
class User {
final String name;
final int age;
User(this.name, this.age);
}
// Можно отправить
isolate.send(User('John', 30));
Важно: Если класс имеет сложные поля (другие объекты, функции) — это не сработает.
4. Числовые типы всех размеров
Int, double, BigInt — все передаются нормально.
bigInt num = BigInt.from(123456789123456789);
isolate.send(num);
Типы данных, которые НЕЛЬЗЯ передавать
1. Функции и замыкания
Нельзя отправить функцию или замыкание в изолят — нарушается правило изоляции:
// Ошибка!
Function myFunction = (x) => x * 2;
isolate.send(myFunction); // Не сработает!
2. Объекты с методами
Объекты классов, которые имеют методы (кроме примитивных getter'ов) — не передаются:
class Database {
void query() { ... }
}
// Ошибка!
isolate.send(Database()); // Не сработает!
3. Future, Stream, и другие async типы
Нельзя отправить Future или Stream в изолят напрямую:
Future<int> future = Future.value(42);
isolate.send(future); // Ошибка!
4. Объекты с native-кодом
Объекты, завёрнутые в нативный код (например, File, Socket), не передаются:
File file = File('/path/to/file');
isolate.send(file); // Ошибка!
5. Объекты с приватными полями (в некоторых случаях)
Это может быть сложным в зависимости от сложности структуры.
6. Рекурсивные структуры данных
Данные, которые ссылаются сами на себя, могут вызвать проблемы.
Способы передачи сложных данных
Если нужно передать сложные данные, есть несколько подходов:
1. Сериализация в JSON
Преобразовать объект в JSON и отправить строку:
class User {
final String name;
final int age;
Map<String, dynamic> toJson() => {
'name': name,
'age': age,
};
factory User.fromJson(Map<String, dynamic> json) {
return User(json['name'], json['age']);
}
}
// Отправить в изолят
String jsonString = jsonEncode(user.toJson());
isolate.send(jsonString);
// В изоляте
User user = User.fromJson(jsonDecode(receivedJson));
2. Использование json_serializable
Для больших приложений лучше использовать генерацию кода:
import 'package:json_annotation/json_annotation.dart';
part 'user.g.dart';
@JsonSerializable()
class User {
final String name;
final int age;
User(this.name, this.age);
factory User.fromJson(Map<String, dynamic> json) => _$UserFromJson(json);
Map<String, dynamic> toJson() => _$UserToJson(this);
}
3. Использование message passing с SendPort
Для более сложных сценариев используй SendPort для двусторонней коммуникации:
SendPort sendPort = await Isolate.spawn(
isolateEntryPoint,
receivePort.sendPort,
);
// Отправить команду в изолят
sendPort.send({
'command': 'process',
'data': 'some data',
});
4. Передача путей вместо объектов
Для файлов и БД передавай пути/ID вместо самих объектов:
// Вместо отправки File
isolate.send('/path/to/file');
// В изоляте открыть файл по пути
File file = File(receivedPath);
Практический пример
void main() async {
final receivePort = ReceivePort();
await Isolate.spawn(
computeHeavyTask,
receivePort.sendPort,
);
final sendPort = await receivePort.first as SendPort;
// Отправить данные
sendPort.send({
'numbers': [1, 2, 3, 4, 5],
'multiplier': 2,
});
// Получить результат
receivePort.listen((message) {
print('Result: $message');
});
}
void computeHeavyTask(SendPort sendPort) {
final receivePort = ReceivePort();
sendPort.send(receivePort.sendPort);
receivePort.listen((message) {
final numbers = message['numbers'] as List<int>;
final multiplier = message['multiplier'] as int;
final result = numbers.map((n) => n * multiplier).toList();
sendPort.send(result);
});
}
Итог
Можно передавать:
- Примитивные типы (int, double, String, bool, null)
- Простые коллекции (List, Map, Set) с sendable элементами
- Простые классы только с примитивными полями
Нельзя передавать:
- Функции и замыкания
- Объекты с методами
- Future, Stream
- Native объекты (File, Socket)
Решение для сложных данных:
- JSON сериализация
- SendPort для двусторонней коммуникации
- Передача путей/ID вместо объектов
Это требует продуманной архитектуры при работе с изолятами.