flutter_native_image icon indicating copy to clipboard operation
flutter_native_image copied to clipboard

Your code should not run on the main thread

Open liuzho opened this issue 6 years ago • 4 comments

Your code should not run on the main thread. This will cause the program to freeze. All IO operations / time-consuming operations should be on the worker thread.

liuzho avatar Apr 03 '20 10:04 liuzho

Your code should not run on the main thread. This will cause the program to freeze. All IO operations / time-consuming operations should be on the worker thread.

Efficiency first.

gwsh avatar Sep 14 '20 09:09 gwsh

Same issue here, I need to display a loader, but UI is stuck by flutter_native_image

JeanChristopheMobizel avatar Feb 03 '21 15:02 JeanChristopheMobizel

You can try to use compute so it will be executed in isolate

giaur500 avatar Apr 15 '21 20:04 giaur500

@giaur500 compute does not have access to Flutter plugins so you will have to use an alternative library such as isolate_handler to construct the isolate. https://pub.dev/packages/isolate_handler

import 'dart:io';
import 'package:flutter_native_image/flutter_native_image.dart';
import 'package:isolate_handler/isolate_handler.dart';

typedef OnFinishedResizing = void Function(bool success);

class ImageResize {

  static final IsolateHandler isolates = IsolateHandler();
  static final String ImageResizeIsolateName = "image-resize";

  static void process(Map<String, String> files, OnFinishedResizing onFinished) {
    isolates.spawn<bool>(
      _onResize,
      name: ImageResizeIsolateName,
      onReceive: (bool success) {
        _finish();

        onFinished(success);
      },
      onInitialized: () => isolates.send(files, to: ImageResizeIsolateName),
    );
  }

  static void _finish() {
    isolates.kill(ImageResizeIsolateName);
  }

  static void _onResize(Map<String, dynamic> context) {
    final HandledIsolateMessenger messenger = HandledIsolate.initialize(context);

    messenger.listen((dynamic files) async {
      if (files is Map<String, String>) {
        if (files.entries.isNotEmpty) {
          await Future.wait(files.entries.map((entry) => _resize(File(entry.key), File(entry.value))));

          messenger.send(true);

          return;
        }
      }

      messenger.send(false);
    });
  }

  static Future<File> _resize(File source, File output) async {
    final int width = 100;
    final int height = 100;
    final File compressed = await FlutterNativeImage.compressImage(
      source.path,
      quality: 90,
      targetWidth: width,
      targetHeight: height,
    );

    output.writeAsBytesSync(compressed.readAsBytesSync(), flush: true);

    return output;
  }

}

To use

final Map<String, String> images = {
  "path to image source 1": "path to image destination 1",
  "path to image source 2": "path to image destination 2",
};

ImageResize.process(images, (bool success) {
  // do something with the resulting images
  images.values.map(print);
});

JamesMcIntosh avatar May 10 '22 17:05 JamesMcIntosh