Multithreading in Flutter using Flutter isolates
In this blog we will be learning how to work with multithreading in Flutter using Flutter Isolates.
Why we need multithreading?
Consider we are developing an application that has intensive use of CPU and performs various operations like Media Conversion, Exporting etc., In such times our app may stop working or hangs waiting for the previous heavy operation to completed. To avoid such condition we have multithreading concept. Here heavy tasks are carried out in a different isolate (i.e. thread), this avoids app crash and ensures smooth app access.
How multithreading achieved in Flutter?
Flutter also provides multithreading feature using Isolates. Isolates are built-in with flutter thus no external dependencies are needed.
How Isolates implemented in flutter?
There are 2 methods to perform
- Using compute
- Using Isolate.spawn
Method 1: Using compute
One of easiest method to perform multithreading in flutter is using compute function. This will execute our code in a different isolate and return the results to our main isolate.
Let’s say we have a class called Person
, which we wish to deserialize from a JSON object:
class Person {
final String name;
Person(this.name);
}
We can add the deserializing code as follows:
Person deserializePerson(String data) {
// JSON decoding is a costly thing its preferable
// if we did this off the main thread
Map<String, dynamic> dataMap = jsonDecode(data);
return Person(dataMap["name"]);
}
Now, to use it with the compute
function, all we need to do is:
Future<Person> fetchUser() async {
String userData = await Api.getUser();
return await compute(deserializePerson, userData);
}
This would internally spawn an isolate, run the decoding logic in it, and return the result to our main isolate.
Method 2: Isolate.spawn
This method is one of the elementary ways to work with isolates, and it should come as no surprise that the compute
method also uses this under the hood.
Here’s what our deserialization code looks like:
Future<Person> fetchUser() async {
ReceivePort port = ReceivePort();
String userData = await Api.getUser();
final isolate = await Isolate.spawn<List<dynamic>>(
deserializePerson, [port.sendPort, userData]);
final person = await port.first;
isolate.kill(priority: Isolate.immediate);
return person;
}void deserializePerson(List<dynamic> values) {
SendPort sendPort = values[0];
String data = values[1];
Map<String, dynamic> dataMap = jsonDecode(data);
sendPort.send(Person(dataMap["name"]));
}