Implement Flutter Dart background process
Introduction.
A background process is a computer process that runs behind the scenes and without user intervention. Typical tasks for these processes include logging, system monitoring, scheduling and user notification. The background process usually is a child process created by a control process for processing a computing task, in flutter that would be an Isolate. After creation, the child process will run on its own, performing the task independent of the control process, freeing the control process of performing that task.
What is an Isolate?
An isolate is a thread that has an event loop that continuously processes events in its own memory space (mini computer with one thread). In effect when the main dart function executes, it executes in an isolate that scans for available events and hangs when none are available, an opportunity for the system to decide to run the garbage collector for example or grab some coffee.
Dart can execute multiple threads by spawning additional isolates.
Creating more isolates can be useful for heavy computation processing but most Flutter apps do not need spawning additional isolates unless it becomes an issue and impacts the frame rate.
Languages such as Java, C++ have multi-threading built-in but it comes at performance costs, especially when it comes to garbage collection. With one thread running and a single memory space per garbage collector, it becomes very efficient as predictable (no mutation possible during garbage collection cycles)
All Dart code runs in an isolate, and code can access classes and values only from the same isolate. Different isolates can communicate by sending values through ports (see ReceivePort, SendPort). Isolates run code in its own event loop, and each event may run smaller tasks in a nested microtask queue.
How Event Loop and Isolates Work
Most modern devices have multi-core CPUs. To take advantage of all those cores, developers sometimes use shared-memory threads running concurrently. However, shared-state concurrency is error prone and can lead to complicated code. Instead of threads, all Dart code runs inside of isolates. Each isolate has its own memory heap, ensuring that none of the state in an isolate is accessible from any other isolate.
Because there’s no shared memory, you don’t have to worry about mutexes or locks. Using isolates, your Dart code can perform multiple independent tasks at once, using additional processor cores if they’re available.
The items in the queue might represent user input, file I/O notifications, timers, and more.
Using Isolates
Because the computation time is unpredictable and could take longer than 5s depending on image size, we'll use isolates to to create sub thread resources to manipulate photos in the background synchronously in the following example.
Isolate.spawn
import 'dart:isolate';
import 'package:image/image.dart' as img;
void main() {
Uint8List testImage = new Uint8List();
double brightness = 10;
Isolate.spawn(computeContrastFunction, ComputePayload(testImage, brightness)).then(results=> {
// do something
});
}
class ComputePayload {
double brightness;
Uint8List image;
constructor(this.image, this.brightnessValue);
}
// heavy task
Future computeContrastFunction(ComputePayload payload) async {
var contrastedImage = img.contrast(decodedImage, payload.brightness);
return contrastedImage;
}
compute function
import 'dart:isolate';
import 'package:image/image.dart' as img;
void main() {
Uint8List testImage = new Uint8List();
double brightness = 10;
compute(computeContrastFunction, ComputePayload(testImage, brightness)).then(results => {
// do something
});
}
class ComputePayload {
double brightness;
Uint8List image;
constructor(this.image, this.brightness);
}
// heavy task
Future computeContrastFunction(ComputePayload payload) async {
var contrastedImage = img.contrast(decodedImage, payload.brightness);
return contrastedImage;
}
Conclusion.
Sources
https://medium.com/flutter-community/thread-and-isolate-with-flutter-30b9631137f3 https://api.flutter.dev/flutter/dart-isolate/Isolate-class.html https://dart.dev/guides/language/concurrency https://hackernoon.com/an-introduction-to-dart-code-and-isolate-em3j34u1https://en.wikipedia.org/wiki/Background_process
Our greatest weakness lies in giving up. The most certain way to succeed is always to try just one more time.