← Назад к вопросам

Что такое Isolate в Dart и когда его использовать?

2.0 Middle🔥 192 комментариев
#Dart#Асинхронность

Комментарии (2)

🐱
claude-haiku-4.5PrepBro AI29 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Isolate в Dart

Isolate (Изолят) — это независимый поток выполнения в Dart с собственной памятью и Event Loop. Это единственный способ в Dart получить настоящую многопоточность, так как обычный код выполняется в одном потоке.

Почему нужны Isolates

Dart работает в одном потоке с Event Loop. Если выполнить тяжёлую операцию (криптография, парсинг JSON, обработка изображений), UI зависнет:

// Плохо: блокирует UI на 5 секунд
void main() async {
  print('Start');
  
  // Тяжёлое вычисление в главном потоке
  final result = await heavyComputation(); // 5 сек
  
  print('Done: $result');
}

Future<int> heavyComputation() async {
  int sum = 0;
  for (int i = 0; i < 1000000000; i++) {
    sum += i;
  }
  return sum;
}

// Результат: UI зависает на 5 сек, кнопки не реагируют, анимация прерывается

Решение: Isolate

import 'dart:isolate';

void main() async {
  print('Start');
  
  // Создаём isolate для тяжёлого вычисления
  final result = await Isolate.run(heavyComputation);
  
  print('Done: $result'); // UI не зависла!
}

int heavyComputation() {
  int sum = 0;
  for (int i = 0; i < 1000000000; i++) {
    sum += i;
  }
  return sum;
}

// Результат: UI остаётся отзывчивым, вычисление выполняется в отдельном потоке

Как работает Isolate

1. Создание простого Isolate (Dart 2.10+)

import 'dart:isolate';

void main() async {
  // Самый простой способ
  final result = await Isolate.run(heavyTask);
  print('Result: $result');
}

int heavyTask() {
  return 42 * 1000000000;
}

2. Традиционный способ (более гибкий)

import 'dart:isolate';

void isolateEntry(SendPort sendPort) {
  // Это выполняется в отдельном isolate
  final result = 42;
  sendPort.send(result); // Отправляем результат в главный isolate
}

void main() async {
  // Создаём ReceivePort для получения данных
  final receivePort = ReceivePort();
  
  // Создаём isolate
  await Isolate.spawn(isolateEntry, receivePort.sendPort);
  
  // Ждём результата
  final result = await receivePort.first;
  print('Result: $result');
}

Двусторонняя коммуникация

import 'dart:isolate';

void isolateEntry(SendPort mainSendPort) {
  // Создаём ReceivePort для получения сообщений из главного isolate
  final isolateReceivePort = ReceivePort();
  
  // Отправляем наш SendPort в главный isolate
  mainSendPort.send(isolateReceivePort.sendPort);
  
  // Слушаем сообщения
  isolateReceivePort.listen((message) {
    print('Isolate received: $message');
    
    // Обработка и отправка результата
    final result = message * 2;
    mainSendPort.send(result);
  });
}

void main() async {
  final receivePort = ReceivePort();
  
  // Создаём isolate
  await Isolate.spawn(isolateEntry, receivePort.sendPort);
  
  // Получаем SendPort изолята
  final isolateSendPort = await receivePort.first as SendPort;
  
  // Отправляем сообщение
  isolateSendPort.send(5);
  
  // Получаем результат
  final result = await receivePort.first;
  print('Main received: $result'); // 10
}

Практические примеры

Пример 1: Обработка изображений

import 'dart:isolate';
import 'package:image/image.dart';

Image processImage(String imagePath) {
  // Читаем и обрабатываем изображение в отдельном потоке
  final image = decodeImage(File(imagePath).readAsBytesSync())!;
  return brightness(image, 50);
}

void main() async {
  // UI остаётся отзывчивым
  final processedImage = await Isolate.run(
    () => processImage('large_image.jpg'),
  );
  
  print('Image processed');
}

Пример 2: Парсинг больших JSON

import 'dart:isolate';
import 'dart:convert';

List<User> parseUsers(String jsonString) {
  final jsonData = jsonDecode(jsonString) as List;
  return jsonData
    .map((json) => User.fromJson(json))
    .toList();
}

void main() async {
  final jsonString = await File('large_file.json').readAsString();
  
  // Парсим в отдельном потоке
  final users = await Isolate.run(
    () => parseUsers(jsonString),
  );
  
  print('Parsed ${users.length} users');
}

Пример 3: Криптография

import 'dart:isolate';
import 'package:crypto/crypto.dart';

String hashPassword(String password) {
  // Хеширование в отдельном потоке
  return sha256.convert(utf8.encode(password)).toString();
}

void main() async {
  final password = 'my_secure_password';
  
  final hash = await Isolate.run(
    () => hashPassword(password),
  );
  
  print('Hash: $hash');
}

Когда использовать Isolate

Используй Isolate для:

  • Обработка больших объёмов данных (JSON, XML)
  • Криптографические операции (хеширование, шифрование)
  • Обработка изображений и видео
  • Сложные математические вычисления
  • Долгие операции ввода-вывода (файлы, БД)
  • Machine Learning инференс

Не используй Isolate для:

  • Простых асинхронных операций (HTTP, таймеры)
  • Коротких операций (< 1мс)
  • Работы с UI (не можешь обновить widget из isolate)

Ограничения Isolates

// Isolates не могут обновлять UI
void isolateEntry(SendPort sendPort) {
  // Это НЕ РАБОТАЕТ:
  // setState(() => counter++); // Error!
  
  // Вместо этого отправляем данные в главный isolate
  sendPort.send(counter);
}

// Isolates не могут использовать некоторые объекты
// (например, HttpClient, которые зависят от главного isolate)

Flutter с Isolates

import 'dart:isolate';
import 'package:flutter/material.dart';

class MyApp extends StatefulWidget {
  @override
  State<MyApp> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  int _result = 0;
  bool _loading = false;
  
  void _startComputation() async {
    setState(() => _loading = true);
    
    // Запускаем тяжёлое вычисление в isolate
    _result = await Isolate.run(heavyComputation);
    
    setState(() => _loading = false);
  }
  
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('Isolate Example')),
      body: Center(
        child: _loading
          ? CircularProgressIndicator()
          : Text('Result: $_result'),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _startComputation,
        child: Icon(Icons.play_arrow),
      ),
    );
  }
}

int heavyComputation() {
  int sum = 0;
  for (int i = 0; i < 1000000000; i++) {
    sum += i;
  }
  return sum;
}

Производительность

  • Создание Isolate — ~1-10мс (небольшие издержки)
  • Передача данных — скопирование (не share), может быть дорого для больших объектов
  • Использование SendPort — очень эффективно для обмена сообщениями

Isolate — это мощный инструмент для масштабирования приложений Flutter на многоядерные процессоры.

Что такое Isolate в Dart и когда его использовать? | PrepBro