What is the difference between isolates and compute ?

Answer

Overview

Both Isolates and

text
compute()
run code in a separate thread to avoid blocking the UI. The difference is that
text
compute()
is a simplified, high-level wrapper around Isolates for simple one-shot tasks.


Flow Diagrams

compute() Flow

text
┌─────────────────────────────────────────────────────────────┐
│                      Main Isolate (UI)                       │
├─────────────────────────────────────────────────────────────┤
│                                                              │
│  1. Call compute(function, data)                            │
│     ↓                                                        │
│  2. Flutter creates new isolate automatically               │
│     ↓                                                        │
└──────────────────────┬──────────────────────────────────────┘
                       │ Spawn & Send Data
┌─────────────────────────────────────────────────────────────┐
│                    Background Isolate                        │
├─────────────────────────────────────────────────────────────┤
│                                                              │
│  3. Receive data parameter                                  │
│     ↓                                                        │
│  4. Execute function(data)                                  │
│     ↓                                                        │
│  5. Return result                                           │
│     ↓                                                        │
│  6. Isolate automatically terminated                        │
│                                                              │
└──────────────────────┬──────────────────────────────────────┘
                       │ Send Result Back
┌─────────────────────────────────────────────────────────────┐
│                      Main Isolate (UI)                       │
├─────────────────────────────────────────────────────────────┤
│                                                              │
│  7. Receive result via Future                               │
│     ↓                                                        │
│  8. Update UI with result                                   │
│                                                              │
└─────────────────────────────────────────────────────────────┘

Lifetime: Short (one task, then exit)
Communication: One-way (data in → result out)
Use case: Simple, one-shot heavy computation

Raw Isolate Flow

text
┌─────────────────────────────────────────────────────────────┐
│                      Main Isolate (UI)                       │
├─────────────────────────────────────────────────────────────┤
│                                                              │
│  1. Create ReceivePort                                      │
│     ↓                                                        │
│  2. Spawn isolate with SendPort                             │
│     ↓                                                        │
└──────────────────────┬──────────────────────────────────────┘
                       │ Spawn with SendPort
┌─────────────────────────────────────────────────────────────┐
│                    Worker Isolate                            │
├─────────────────────────────────────────────────────────────┤
│                                                              │
│  3. Receive Main's SendPort                                 │
│     ↓                                                        │
│  4. Create own ReceivePort                                  │
│     ↓                                                        │
│  5. Send back own SendPort to Main                          │
│     ↓                                                        │
│  6. Listen for messages (loop)                              │
│                                                              │
└──────────────────────┬──────────────────────────────────────┘
                       │ Send Own SendPort
┌─────────────────────────────────────────────────────────────┐
│                      Main Isolate (UI)                       │
├─────────────────────────────────────────────────────────────┤
│                                                              │
│  7. Receive Worker's SendPort                               │
│     ↓                                                        │
│  8. Send Message #1 ────────────────────┐                  │
│                                          │                   │
│  9. Send Message #2 ──────────────────┐ │                  │
│                                        │ │                   │
│  10. Send Message #N ────────────────┐│ │                  │
│                                      ││ │                   │
└──────────────────────────────────────┼┼─┼───────────────────┘
                                       ││ │
                      Messages Queue   ↓↓ ↓
┌─────────────────────────────────────────────────────────────┐
│                    Worker Isolate                            │
├─────────────────────────────────────────────────────────────┤
│                                                              │
│  ┌──────────────────────────────────────┐                  │
│  │  Message Loop (continuous)           │                  │
│  │                                      │                  │
│  │  11. Receive Message #1              │                  │
│  │      ↓                               │                  │
│  │  12. Process & Send Result #1 ───────┼──────┐          │
│  │      ↓                               │      │           │
│  │  13. Receive Message #2              │      │           │
│  │      ↓                               │      │           │
│  │  14. Process & Send Result #2 ───────┼──────┤          │
│  │      ↓                               │      │           │
│  │  15. Keep listening... (loop)        │      │           │
│  │                                      │      │           │
│  └──────────────────────────────────────┘      │           │
│                                                 │           │
└─────────────────────────────────────────────────┼───────────┘
                                Results Back      ↓
┌─────────────────────────────────────────────────────────────┐
│                      Main Isolate (UI)                       │
├─────────────────────────────────────────────────────────────┤
│                                                              │
│  16. Receive Result #1                                      │
│      ↓                                                       │
│  17. Update UI                                              │
│      ↓                                                       │
│  18. Receive Result #2                                      │
│      ↓                                                       │
│  19. Update UI                                              │
│      ↓                                                       │
│  20. Continue... (ongoing)                                  │
│                                                              │
│  Later: isolate.kill() to terminate                         │
│                                                              │
└─────────────────────────────────────────────────────────────┘

Lifetime: Long-lived (until explicitly killed)
Communication: Bidirectional (continuous messaging)
Use case: Persistent worker, multiple tasks, ongoing processing

Side-by-Side Comparison

text
┌──────────────────────────┬──────────────────────────┐
│      compute()           │     Raw Isolate          │
├──────────────────────────┼──────────────────────────┤
│                          │                          │
│  Main Isolate            │  Main Isolate            │
│       │                  │       │                  │
│       │ compute()        │       │ Isolate.spawn()  │
│       ↓                  │       ↓                  │
│  ┌─────────┐            │  ┌─────────┐            │
│  │ Background│           │  │  Worker │            │
│  │ Isolate  │           │  │ Isolate │            │
│  │          │           │  │         │            │
│  │ Run once │           │  │ Run loop│            │
│  │ Exit auto│           │  │ Stay alive│          │
│  └─────────┘            │  └─────────┘            │
│       │                  │       │  ↑              │
│       │ Result           │       │  │ Multiple     │
│       ↓                  │       │  │ Messages     │
│  Main Isolate            │       ↓  │              │
│                          │  Main Isolate            │
│  ✅ Simple               │       │  │              │
│  ✅ Automatic cleanup    │       │  │              │
│  ❌ One-shot only        │  ✅ Bidirectional       │
│                          │  ✅ Long-lived          │
│                          │  ❌ Complex setup       │
│                          │                          │
└──────────────────────────┴──────────────────────────┘

Memory Model

text
┌─────────────────────────────────────────────────────────────┐
│                     Dart Memory Model                        │
├─────────────────────────────────────────────────────────────┤
│                                                              │
│  Main Isolate                      Worker Isolate           │
│  ┌──────────────────┐             ┌──────────────────┐     │
│  │ Heap Memory      │             │ Heap Memory      │     │
│  │                  │             │                  │     │
│  │ • UI Objects     │             │ • Compute Data   │     │
│  │ • State          │   NO        │ • Work Results   │     │
│  │ • Controllers    │  SHARED     │ • Temp Objects   │     │
│  │ • Variables      │  MEMORY!    │ • Variables      │     │
│  │                  │             │                  │     │
│  └──────────────────┘             └──────────────────┘     │
│           │                                │                │
│           │                                │                │
│           │   Message Passing (Copy)       │                │
│           └────────────────────────────────┘                │
│                                                              │
│  ⚠️ Important: Data is COPIED between isolates             │
│     - No shared memory access                               │
│     - Prevents race conditions                              │
│     - Each isolate has its own heap                         │
│                                                              │
└─────────────────────────────────────────────────────────────┘

compute() — Simple Background Work

text
compute()
is a Flutter helper function that:

  1. Spawns a new isolate
  2. Runs your function in it
  3. Returns the result
  4. Closes the isolate automatically
dart
import 'package:flutter/foundation.dart';

// The function to run in background (must be top-level or static)
List<Post> _parsePosts(String jsonStr) {
  final list = jsonDecode(jsonStr) as List;
  return list.map((e) => Post.fromJson(e)).toList();
}

// Usage — clean and simple
Future<List<Post>> loadPosts(String jsonStr) async {
  return await compute(_parsePosts, jsonStr);
  // ↑ Runs _parsePosts in a new isolate with jsonStr as argument
}

✅ One function, one argument, one return value — that's it.


Isolate — Full Control

Raw

text
Isolate.spawn()
gives full control — bidirectional communication, long-lived isolates, multiple messages.

dart
import 'dart:isolate';

void workerIsolate(SendPort sendPort) {
  // This runs in a separate isolate
  final receivePort = ReceivePort();
  sendPort.send(receivePort.sendPort); // Send back our port

  receivePort.listen((message) {
    if (message is int) {
      // Do heavy work
      int result = message * message;
      sendPort.send(result); // Send result back
    }
  });
}

Future<void> runWithIsolate() async {
  final receivePort = ReceivePort();
  await Isolate.spawn(workerIsolate, receivePort.sendPort);

  final SendPort workerPort = await receivePort.first;

  // Send multiple messages
  workerPort.send(5);
  workerPort.send(10);
  workerPort.send(20);

  await for (final result in receivePort) {
    print('Result: $result');
  }
}

Key Differences

Feature
text
compute()
Raw
text
Isolate
Ease of use✅ Very simple⚠️ Complex setup
DirectionOne-way: input → outputBidirectional messaging
LifetimeShort-lived (exits after return)Can be long-lived
Multiple messages❌ One call, one result✅ Many messages
Function signature
text
T Function(Q)
Any function
Under the hoodUses Isolate internallyDirect Isolate API
Best forOne-time heavy computationOngoing background worker

When to Use Which

Use CaseRecommendation
Parse large JSON from API
text
compute()
Compress/resize images
text
compute()
Run FFT or math calculations
text
compute()
Background download managerRaw
text
Isolate
Persistent worker (multiple requests)Raw
text
Isolate
Real-time audio/video processingRaw
text
Isolate

Flutter 3.7+ — Isolate.run()

Flutter added

text
Isolate.run()
as a simpler alternative to raw Isolate that is similar to
text
compute()
:

dart
// Flutter 3.7+ — cleaner syntax
final result = await Isolate.run(() {
  // Heavy computation
  return heavyProcess(data);
});

Example: compute vs raw Isolate

dart
// ✅ Use compute for simple one-shot heavy task
Future<String> encryptData(String data) async {
  return await compute(_encrypt, data);
}

String _encrypt(String input) {
  // CPU-heavy encryption
  return performEncryption(input);
}

// ✅ Use raw Isolate for ongoing background processing
class BackgroundProcessor {
  late Isolate _isolate;
  late SendPort _sendPort;

  Future<void> start() async {
    final receivePort = ReceivePort();
    _isolate = await Isolate.spawn(_worker, receivePort.sendPort);
    _sendPort = await receivePort.first;
  }

  void processItem(dynamic item) => _sendPort.send(item);

  void stop() => _isolate.kill();
}

Summary: Use

text
compute()
for simple, one-shot background tasks. Use raw
text
Isolate
when you need a persistent worker, bidirectional communication, or multiple message exchanges.