Use Isolates to prevent UI Jank | Flutter multiprocessing

ramgendeploy

Ramiro - Ramgen

Posted on August 21, 2022

Use Isolates to prevent UI Jank | Flutter multiprocessing

As you might know flutter runs asynchronously on a single thread often called the main thread and also where the UI is running, now when you need to run heavy computational function you find that you app freezes and janks because is busy with that function.

Here is where Isolates come into action, this is a way to spawn threads in dart/flutter and prevent the main thread to halt.

Isolates are a little finicky but they are useful when the situation comes and this was the perfect situation, I needed to load an image and send it to an API for processing, this was janking the main thread but it can be done on an isolate and prevent that.

Let's see one of the easiest ways of using isolates with the compute function

Function to run

First we need a function to execute, this function loads the image and sends it with http to the API.

Future<Uint8List?> requestImg(RequestInputs reqInputs) async {
  File file = File(reqInputs.filePath!);

  final http.MultipartRequest request = http.MultipartRequest(
    'POST',
    Uri.parse('server:uri'),
  );
  final Map<String, String> headers = <String, String>{'Content-type': 'multipart/form-data'};

  final img_proc.Image tmp = img_proc.decodeImage(await file.readAsBytes())!;
  final List<int> tosend = img_proc.encodeJpg(tmp);

  request.files.add(http.MultipartFile.fromBytes(
    'file',
    tosend,
    filename: 'aism_source',
    contentType: MediaType('image', 'jpeg'),
  ));

  request.headers.addAll(headers);
  request.fields.addAll(reqInputs.settings);
  final http.StreamedResponse res = await request.send();
  debugPrint('Request settings sent');

  Uint8List responseImage = await res.stream.toBytes();
  return responseImage;
}
Enter fullscreen mode Exit fullscreen mode

Now my function needed more than one argument but the compute function only accepts functions with one, to solve this I use a custom class to pass all of the data.

class RequestInputs {
  final String? filePath;
  final Map<String, String> settings;

  RequestInputs(this.filePath, this.externalPath, this.settings);
}
Enter fullscreen mode Exit fullscreen mode

Compute function

Great we have the function and the custom class let's see how to use compute to run it on an isolate.

// #1
compute<StickerRequestInputs, Uint8List?>(
  requestImg,
  StickerRequestInputs(
    imgPath,
    storage,
    settings,
  ),
// #2
).then((value) => setState(() {
      loading = false;
      if (value != null) {
        imgBytes = value;
        saveImage(value);
      } else {
        debugPrint('Error!');
      }
    }));
Enter fullscreen mode Exit fullscreen mode

We first need to declare the function input and output types in the compute statement #1 compute<Q,R> Q is the input type and R is the return type.

Then we pass the function and the input to run, in this case we instantiate the custom class that we declared.

The compute is a future of the return type R #2, we can use either async or .then to do something after it finishes, in this case we update the state with the new data or we print an error if it fails.

Watch the video for a walkthrough of all the code, subscribe to see the progress of the app :D

Alright and that's it, I will continue working with isolates and see what we can do with them, but as i said the are a little tricky to work with regardless they are a good option when you need them.

💖 💪 🙅 🚩
ramgendeploy
Ramiro - Ramgen

Posted on August 21, 2022

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related

Changing App Icon in Flutter
flutter Changing App Icon in Flutter

November 14, 2024

Flutter - Responsive Spacing
flutter Flutter - Responsive Spacing

September 11, 2024

Problem by running App on Phone
flutter Problem by running App on Phone

September 9, 2024

Flutter AdMob Rewarded Ads
flutter Flutter AdMob Rewarded Ads

September 30, 2024