Flutter Isolates
Flutter is single-threaded by default, which means that long-running tasks can block the UI and make your app feel sluggish. To handle heavy computations without freezing the interface, Flutter provides Isolates, which are separate threads that run independently and communicate via messages.
In this article, we’ll explore how to use Flutter Isolates to perform continuous background calculations (like a Fibonacci sequence sum) while keeping the UI responsive.
🧩 What is an Isolate?
- An Isolate is a separate thread of execution.
- Memory is not shared between isolates. They communicate by sending messages through
SendPortandReceivePort. - Ideal for CPU-intensive tasks, like complex calculations or processing large data.
🚀 Example: Continuous Fibonacci Sum
We’ll create a Flutter app that continuously calculates a Fibonacci-like cumulative sum in the background and updates the UI in real-time.
1️⃣ The Background Task
Get Rugved Apraj’s stories in your inbox
Join Medium for free to get updates from this writer.
The isolate needs a function that runs independently. Here’s how we define it:
static void isolationMethod(List<dynamic> params) async {
SendPort sendPort = params[0]; // SendPort to communicate with main isolate
int firstValue = 0;
int secondValue = 1;
int sum = 0;
while (true) {
int newValue = firstValue + secondValue;
sum += newValue;
firstValue = secondValue;
secondValue = newValue;
// Send the updated sum back to the main thread
sendPort.send(sum);
// Pause briefly to simulate work
await Future.delayed(const Duration(milliseconds: 200));
}
}Explanation:
params[0]is the SendPort used to send messages back to the main thread.- The loop continuously computes the next number in the Fibonacci sequence.
- After calculating, it sends the updated sum back.
- The delay simulates a real-world background task without overwhelming the CPU.
2️⃣ Setting Up the Isolate
To start an isolate, we need a ReceivePort to listen to messages:
ReceivePort receivePort = ReceivePort();
// Launch the isolate
Isolate.spawn(isolationMethod, [receivePort.sendPort]);
// Listen for messages from the isolate
receivePort.listen((message) {
setState(() {
sum = message; // Update UI with the latest sum
});
});Explanation:
ReceivePortopens a communication channel.Isolate.spawn()starts the background computation.- Messages are received asynchronously and update the UI via
setState.
3️⃣ Full Flutter Example
Here’s a complete working Flutter app:
import 'dart:isolate';
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return const MaterialApp(
home: IsolateExample(),
);
}
}
class IsolateExample extends StatefulWidget {
const IsolateExample({super.key});
@override
State<IsolateExample> createState() => _IsolateExampleState();
}
class _IsolateExampleState extends State<IsolateExample> {
int sum = 0;
Isolate? _isolate;
ReceivePort? _receivePort;
static void isolationMethod(List<dynamic> params) async {
SendPort sendPort = params[0];
int firstValue = 0;
int secondValue = 1;
int sum = 0;
while (true) {
int newValue = firstValue + secondValue;
sum += newValue;
firstValue = secondValue;
secondValue = newValue;
sendPort.send(sum);
await Future.delayed(const Duration(milliseconds: 200));
}
}
Future<void> _startIsolate() async {
_receivePort = ReceivePort();
_isolate = await Isolate.spawn(
isolationMethod,
[_receivePort!.sendPort],
);
_receivePort!.listen((message) {
setState(() => sum = message);
});
}
void _stopIsolate() {
_isolate?.kill(priority: Isolate.immediate);
_isolate = null;
_receivePort?.close();
setState(() => sum = 0);
}
@override
void dispose() {
_stopIsolate();
super.dispose();
}
@override
Widget build(BuildContext context) {
final isRunning = _isolate != null;
return Scaffold(
appBar: AppBar(title: const Text('Flutter Isolates Example')),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text('Sum from Isolate:', style: Theme.of(context).textTheme.headlineSmall),
const SizedBox(height: 10),
Text('$sum', style: Theme.of(context).textTheme.displaySmall?.copyWith(
fontWeight: FontWeight.bold,
color: Colors.blueAccent,
)),
const SizedBox(height: 30),
ElevatedButton.icon(
icon: Icon(isRunning ? Icons.stop : Icons.play_arrow),
label: Text(isRunning ? 'Stop Isolate' : 'Start Isolate'),
onPressed: isRunning ? _stopIsolate : _startIsolate,
),
],
),
),
);
}
}








