was originally a single-threaded programming language. However, many have heard of Isolate. They are often asked about in Flutter developer interviews. For this reason alone, it is worth studying this topic in a little more detail. Dart Today we will figure out what they are and how they can help us create responsive interfaces that work with 60 fps. What is Isolate? Any Dart code is executed in Isolate. Isolate is an isolated environment, inside which there is memory allocated to it and its EventLoop. Each Isolate is single-threaded and can only manage the memory and EventLoop allocated for it. You cannot control the memory of another Isolate. How do different Isolates communicate? Communication between Isolates occurs through the transfer of messages between ports. How do I start using Isolates in my applications? So, to use this powerful tool, we need to include the Dart library: isolates If we look at the documentation, we will see a rather small API that gives us the following main classes to work with: - A non-counterfeit object that returns the same when passing through other isolates. That is, we can receive this object in no other way, except by sending some object to the isolate and receiving it back. Capability - Isolate or isolated context of the execution of Dart code. Isolate is what allows our isolates to communicate with each other through messaging. Inherits the Stream interface. It should be noted that RecievePort is a Single subscription stream, which means it can only have one listener. It has a sendPort getter that returns an instance of the SendPort class, which is discussed later. RecievePort is a class that can send messages to RecievePort. SendPort inherits the Capability interface. SendPort When should I use Isolate? So there are two surefire cases when you should resort to Isolate. Suppose you need to complete a sizeable one-time task. For example, de- / serialization of data, receiving a large response from the server, some complex mathematical calculations (Fibonacci number), etc. You can isolate someone else's poorly optimized code so that you do not rewrite it. Thus, you will protect yourself from a drop in your application's performance due to the fault of any massive libraries or non-optimal code of another person. Basic example ; ; main() { runApp(MyApp()); } { @override Widget build(BuildContext context) { MaterialApp( home: MyHomePage(), ); } } { @override _MyHomePageState createState() => _MyHomePageState(); } { Isolate isolate; ReceivePort receivePort; @override initState() { .initState(); spawnNewIsolate(); } spawnNewIsolate() { receivePort = ReceivePort(); { isolate = Isolate.spawn(sayHello, receivePort.sendPort); print( ); receivePort.listen((dynamic message) { print( ); }); } (e) { print( ); } } sayHello(SendPort sendPort) { sendPort.send( ); } @override dispose() { .dispose(); receivePort.close(); isolate.kill(); } @override Widget build(BuildContext context) { Scaffold( appBar: AppBar( title: Text( ), ), : Center(), ); } } import 'dart:isolate' import 'package:flutter/material.dart' void class MyApp extends StatelessWidget return class MyHomePage extends StatefulWidget < > class _MyHomePageState extends State MyHomePage void super void async try await "Isolate: $isolate" 'New message from Isolate: $message' catch "Error: $e" //spawn accepts only static methods or top-level functions static void "Hello from Isolate" void super return "Isolate Demo" body Compute So we figured out how to spawn a new isolate. Now let's look at more convenient ways of working with isolates, and the first of them will be the built-in wrapper over Isolate Api in Flutter - Compute. Compute slightly expands the capabilities of working with isolates in Flutter and takes on the following responsibilities: Isolate creation Transfer task to isolate Completing this task Returning a response Closing ports Isolate destruction Thus, all you need to use the compute function is to pass the first argument to the function that you want to execute in the isolate, and the second argument to pass those arguments that should go to the executable function. Basic example ; ; main() { runApp(MyApp()); } { @override Widget build(BuildContext context) { MaterialApp( home: MyHomePage(), ); } } { @override _MyHomePageState createState() => _MyHomePageState(); } { @override initState() { .initState(); createComputeFunction(); } createComputeFunction() { answer; answer = compute(sayHelloFromCompute, ); print( ); } sayHelloFromCompute( string) { string; } @override Widget build(BuildContext context) { Scaffold( appBar: AppBar( title: Text( ), ), : Center(), ); } } import 'package:flutter/foundation.dart' import 'package:flutter/material.dart' void class MyApp extends StatelessWidget return class MyHomePage extends StatefulWidget < > class _MyHomePageState extends State MyHomePage void super void async String await 'Hello' "Answer from compute: $answer" static String String return return "Isolate Demo" body Third-party solutions We have already mastered the skills of working with isolates and know how to use the compute function. Today there are two third-party libraries for working with isolates. computer - https://pub.dev/packages/computer Creating a limited number of workers Distribution of tasks between the created workers Task queue management worker_manager - https://pub.dev/packages/worker_manager Creation of a pool of isolates, which itself is replenished with new ones when one of the isolates is destroyed Works through streams Allows you to set work timeouts (kills isolate after a specified time in case the task is too resource-intensive) Ability to stop calculations You can already familiarize yourself with them in more detail and see examples of work in the documentation. Representative example However, we have not yet looked at the most illustrative example showing the importance of performing complex operations in separate isolates. ; ; main() { runApp(MyApp()); } { @override Widget build(BuildContext context) { MaterialApp( home: MyHomePage(), ); } } { @override _MyHomePageState createState() => _MyHomePageState(); } { AnimationController rotationController; Animation animation; List<int> results = []; @override initState() { .initState(); rotationController = AnimationController( duration: Duration(seconds: ), : , )..addListener( setState(() {})); animation = Tween(begin: , : ).animate(rotationController); rotationController.forward( : ); animation.addStatusListener((status) { (status == AnimationStatus.completed) { rotationController.repeat(); } }); } @override Widget build(BuildContext context) { Scaffold( appBar: AppBar( title: Text( ), ), : Column( children: [ SizedBox( height: , ), Center( child: RotationTransition( turns: animation, : Container( width: , : , : Colors.orange, ), ), ), SizedBox( height: , ), RaisedButton( onPressed: () { setState(() { final result = fib( ); print(result); results.add(result); }); }, : Text( ), ), RaisedButton( onPressed: () { final result = compute(fib, ); setState(() { results.add(result); }); }, : Text( ), ), Text( ) ], ), ); } } int fib(int n) { (n < ) { n; } fib(n - ) + fib(n - ); } import 'package:flutter/foundation.dart' import 'package:flutter/material.dart' void class MyApp extends StatelessWidget return class MyHomePage extends StatefulWidget < > class _MyHomePageState extends State MyHomePage with TickerProviderStateMixin void super const 5 vsync this => () 0.0 end 1.0 from 0.0 //loop the animation for clarity if return "Isolate Demo" body 100 child 200 height 200 color 100 40 child "fib(40) in main thread" async await 40 child "fib(40) in isolate" "Number of results: ${results.length.toString()}" if 2 return return 2 1 Additional resources https://api.dart.dev/stable/2.10.3/dart-isolate/dart-isolate-library.html Sergey Lavinov - Isolates in combat conditions https://www.youtube.com/watch?v=sdLBKUWovqs Daniil Surnin - Competently designed domain and isolates on guard 60 fps https://www.youtube.com/watch?v=_lyESd-fLWM Isolates and Event Loops - Flutter in Focus https://www.youtube.com/watch?v=vl_AaCgudcY Dart asynchronous programming: Isolates and event loops https://medium.com/dartlang/dart-asynchronous-programming-isolates-and-event-loops-bffc3e296a6a https://api.flutter.dev/flutter/foundation/compute.html https://pub.dev/packages/worker_manager/example https://pub.dev/packages/computer https://gbksoft.com/blog/flutter-vs-react-native-a-developers-perspective/ About the Author Sergey Vedmediev Flutter Developer at GBKSOFT Having started my career as a front-end developer; at some point, I got to start learning Flutter. Despite my moderate experience with it, I was able to switch to building beautiful cross-platform applications quickly. I think this technology, and in particular, the Dart language is much more promising and exciting. FAQ: What is Isolate? Isolate - an isolated environment within which Dart code is executed with its own allocated memory (heap) and its own (separate) EventLoop. What are they needed for? They are needed to perform complex operations in separate threads and not affect performance in the main thread (main/ui-thread). How do I use them? The dart:isolate library in Dart or the compute function in Flutter or third-party Flutter libraries.