Isolates in Flutter are like separate rooms where your app can do heavy work without bothering the main room (your UI thread). This keeps your app smooth and responsive.
Why Use Isolates?
If you have a task that takes a long time, like processing a large file or doing complex calculations, running it on the main UI thread will freeze your app. Isolates let you run these tasks in the background.
How to Communicate?
Isolates don't share memory, so they need a way to talk to each other. This is done using Ports.
Understanding Ports
SendPort
: Like an address to send messages to.ReceivePort
: Like a mailbox to listen for incoming messages.
When you start an Isolate, you give it a SendPort
to talk back to the main UI. The Isolate itself can create its own SendPort
and send it to the main UI so the main UI can talk to the Isolate.
Starting an Isolate and Talking
You start an Isolate using Isolate.spawn
. You give it a function to run in the new Isolate and some initial data. Often, the initial data is the SendPort
of a ReceivePort
set up in the main UI.
The Communication Flow
The Isolate function then sets up its own ReceivePort
and sends its SendPort
back to the main UI through the SendPort
it received. Now, the main UI has the Isolate's SendPort
(to send data to the Isolate) and the Isolate has the main UI's SendPort
(to send data back to the main UI). They can now send messages (like strings, numbers, or basic objects) to each other.
Don't Forget to Clean Up!
When your background task is finished, or if the user leaves the page, it's really important to stop the Isolate to save resources. Make sure you have a way to close the communication channels and kill the Isolate when it's no longer needed.
Compute for Much Simpler
We shownly the basic way to use Isolates. But Flutter has a built-in function called compute
that makes it much easier to run tasks in the background.
It handles the port communications for you, so you just need to write the function that does the work and call compute
with it.
But still you need the function to run be a top-level function, not a method of a class.
final result = await compute(
myFunction,
myData,
);
where myData is a simple object containing only basic types (like int, double, String, List, Map) and myFunction is a top-level function that takes the data and returns a result.