Multithreading in Flutter : Know All About Isolates in Flutter

Multithreading in Flutter : Know All About Isolates in Flutter

By enabling numerous threads or processes to execute simultaneously, multithreading in Flutter is a technique used in enterprise software development to increase performance and responsiveness. Multithreading can be utilized in the context of Flutter to assign CPU-intensive or tedious tasks away from the main thread, which is in charge of processing user input and updating the UI.

Isolates are small, lightweight threads that operate independently of the main thread and share a different memory space, and Flutter comes with built-in support for multithreading. Isolates can exchange messages with one another, but they are unable to share memory or state.

Use of Isolates for Multithreading in Flutter

When using isolates in Flutter, we may create a new isolate by calling the Isolate.spawn method, and we can also pass a callback function to execute inside the isolate. To use Isolate.spawn, follow this example:

For use the multithreading, first we have to import the isolate.

import 'dart:isolate';

Then use the Isolate.spawn function

void _runInBackground() async {
 final ReceivePort receivePort = ReceivePort();

await Isolate.spawn(_backgroundTask, receivePort.sendPort);
 receivePort.listen((message) {
   print('Received message: $message');
 });
}
void _backgroundTask(SendPort sendPort) {
 // Do some background task
 final result = 42;
 // Send result back to the main thread
 sendPort.send(result);
}

In this example, we make a new isolate with the use of Isolate.spawn a callback function called _backgroundTask and provide it’s input. The SendPort object is supplied as a parameter to the _backgroundTask method, which performs a background task and then transmits the outcome back to the main thread.

To receive messages from the isolation, we build a ReceivePort object on the main thread. After that, we watch the ReceivePort for messages and print them out as soon as they come in.

Compute function to use with isolates

Although isolates offer a mechanism for eliminating CPU-intensive processes from the main thread, using them directly can be a little challenging. The compute function, a high-level API that enables us to execute a function in an isolate and receive the result as a Future, fortunately, offers a simpler method of using isolates in Flutter.

Here is an illustration of how to combine a Fibonacci function with the calculate function:

import 'package:flutter/foundation.dart';

int fibonacci(int n) {
 if (n == 0 || n == 1) {
   return n;
 } else {
   return fibonacci(n - 1) + fibonacci(n - 2);
 }
}
void main() async {
 final result = await compute(fibonacci, 40);
 print('Fibonacci result: $result');
}

In this illustration, we build an easy Fibonacci function that recursively calculates the nth Fibonacci number. The compute function is then called together with the 40th parameter and the fibonacci function. The compute function uses a separate isolate to perform the fibonacci function and returns a Future that resolves to the outcome.

Isolate a ComputeService

Using isolates with a ComputeService is made simple by Flutter. A utility class called a ComputeService makes it easier to execute a function in an isolate and return the results to the main thread.

Here is a sample of how to conduct a costly computation using the ComputeService:

import 'dart:async';

void main() async {
  final result = await ComputeService.compute(fibonacci, 40);
  print('Fibonacci result: $result');
}

int fibonacci(int n) {
  if (n == 0 || n == 1) {
    return n;
  }
  return fibonacci(n - 1) + fibonacci(n - 2);
}

class ComputeService {
  static Future<dynamic> compute(Function function, dynamic arg) async {
    final response = Completer<dynamic>();
    final isolate = await Isolate.spawn(_spawnIsolate as void Function(Null message), null);
    final sendPort = ReceivePort();
    isolate.addOnExitListener(sendPort.sendPort);
    isolate.ping(sendPort.sendPort);
    sendPort.listen((message) {
      if (message is SendPort) {
        message.send(arg);
      } else {
        response.complete(message);
      }
    });
    return response.future;
  }

  static void _spawnIsolate(SendPort sendPort) {
    final receivePort = ReceivePort();
    sendPort.send(receivePort.sendPort);
    receivePort.listen((message) {
      final result = Function.apply(message, [40]);
      sendPort.send(result);
    });
  }
}

In this illustration, we develop a calculate method that accepts a function as a parameter, returns a Future, and resolves to the outcome of calling the function in a different isolation.

A Completer object is first created by the compute method to retain the isolate’s response. Then, it uses the _spawnIsolate function to spawn fresh isolation while monitoring a ReceivePort object for messages.

To receive messages from the main thread, a new ReceivePort object is created in the _spawnIsolate function. So that it can interact with the isolate, we then return the SendPort object of the ReceivePort to the main thread.

When a message is received on the SendPort on the main thread, we verify whether it is a SendPort object. If so, we use the SendPort to deliver the argument to the isolation. If not, the function’s output from the isolate is used to complete the Completer object.

We can invoke the compute method with a function and an argument to make use of the ComputeService:

void main() async {
 final result = await ComputeService.compute(fibonacci, 40);
 print('Fibonacci result: $result');
}

In this example, the Fibonacci function and the integer number 40 are passed as arguments when calling the compute method. The Fibonacci function is executed in an isolate by the ComputeService, which then returns the result as a Future. The outcome is then printed to the console.

Flutter Developers from Flutter Agency

Conclusion

This tutorial taught us how to conduct expensive tasks in Flutter without stopping the user interface by using isolates. We also learnt about Flutter’s ComputeService, a useful utility class that makes it easy to perform functions in isolated contexts. We can create high-performance Flutter applications that deliver a fluid user experience even for computationally demanding activities by utilising isolates and the ComputeService.

To hire Flutter developers who will assist and maintain your projects and create applications that function flawlessly, get in touch with the leading Flutter application development company in USA.

Frequently Asked Questions (FAQs)

1. In Flutter, how do you make multiple threads?

Dart/Flutter only supports a single thread and cannot exchange global variables. Considering that every isolate has its own memory, space, and everything. You must employ isolates to make it function like a multi-threaded programme, and message-based communication will be done through ports.

2. How multithreading in Flutter works?

A programme can run more quickly by using several CPUs or cores by using multithreading, which enables the simultaneous execution of two or more components of the programme. By enabling the programme to carry out numerous jobs at once, it can also become more user-responsive.

3. What issues is multithreading meant to solve?

Multiple app components can run simultaneously when a programme is multithreaded. These components, which are available within the process and are referred to as threads, are lightweight. Using parallelism, threads enhance the performance of the mobile application. They exchange information like as files, data segments, and code segments, etc.

Book Your Flutter Developer Now

Abhishek Dhanani

Written by Abhishek Dhanani

Abhishek Dhanani, a skilled software developer with 3+ years of experience, masters Dart, JavaScript, TypeScript, and frameworks like Flutter and NodeJS. Proficient in MySQL, Firebase, and cloud platforms AWS and GCP, he delivers innovative digital solutions.

Leave a comment

Your email address will not be published. Required fields are marked *


ready to get started?

Fill out the form below and we will be in touch soon!

"*" indicates required fields

✓ Valid number ✕ Invalid number