Можно ли передать пользовательский класс в изолят в Dart?

«Можно ли передать пользовательский класс в изолят в Dart?» — вопрос из категории Асинхронность, который задают на 29% собеседований Flutter Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Да, но с важными ограничениями. Поскольку изоляты в Dart не разделяют память и работают в отдельных потоках, передаваемые объекты должны быть сериализуемыми. Это означает, что можно передавать:

  • Примитивные типы (int, double, bool, String, null)
  • Коллекции (List, Map, Set) из сериализуемых элементов
  • Пользовательские классы, которые можно преобразовать в простые структуры данных

Пример передачи класса через сериализацию:

// Класс с методами сериализации/десериализации
class UserData {
  final String name;
  final int id;
  final List<String> tags;

  UserData(this.name, this.id, this.tags);

  // Преобразование в Map для передачи
  Map<String, dynamic> toJson() => {
    'name': name,
    'id': id,
    'tags': tags,
  };

  // Восстановление из Map
  factory UserData.fromJson(Map<String, dynamic> json) => 
      UserData(json['name'], json['id'], List<String>.from(json['tags']));
}

// В основном изоляте
void spawnIsolate() async {
  final receivePort = ReceivePort();
  final isolate = await Isolate.spawn(
    _isolateEntry,
    receivePort.sendPort,
  );

  // Отправляем данные в изолят
  final userData = UserData('John', 1, ['admin', 'premium']);
  receivePort.sendPort.send(userData.toJson());
}

// Функция-точка входа изолята
void _isolateEntry(SendPort mainSendPort) {
  final receivePort = ReceivePort();
  mainSendPort.send(receivePort.sendPort);

  receivePort.listen((message) {
    if (message is Map) {
      // Десериализуем полученные данные
      final data = UserData.fromJson(Map<String, dynamic>.from(message));
      print('Received in isolate: ${data.name}, ${data.id}');
    }
  });
}

Ключевые ограничения:

  1. Нельзя передать объект с методами или замыканиями — передаются только данные
  2. Сложные графы объектов требуют полной сериализации всех связанных объектов
  3. Для автоматической сериализации используйте пакеты типа json_serializable или freezed
  4. Производительность: сериализация/десериализация добавляют накладные расходы

На практике я часто использую freezed для создания иммутабельных классов с автоматической сериализацией, что упрощает работу с изолятами.