Where Isolate can be defined in Flutter? How to start a thread in Flutter?

4,106

You should read https://dev.to/alphamikle/why-should-you-use-isolates-in-flutter-1k5o, and look at package:isolates.

The article contrasts using main thread, compute, Isolate proper, and the isolates package, with advantages and disadvantages of each. Best article I've seen in a long time.

Also keep in mind, Java threads are data-shared, leading to possible deadlocks. Dart isolates are share-nothing, using "ports" to carefully move data between isolates, and no need for locking!

Share:
4,106
user10475643
Author by

user10475643

Updated on December 28, 2022

Comments

  • user10475643
    user10475643 over 1 year

    I am a new in Flutter, so the question can be kind of obvious, but I can't find any answer on the Internet.

    I have a Flutter application with some screens and I would say on the fifth screen I have a button, which should trigger some heavy computation work (converting thousands of images). On the same screen there is a progress bar and it is supposed to display the progress.

    I am puzzled how to implement that technically. The triggering is happening obviously on onPressed of the button.

    • if I simply call a Future<void> function, then the UI is freezing completely for the time of processing, which is obviously is not desired behavior
    • if I put my function inside compute, on the first await I get exception Unhandled Exception: Exception: ServicesBinding.defaultBinaryMessenger was accessed before the binding was initialized. If you're running an application and need to access the binary messenger before runApp() has been called (for example, during plugin initialization), then you need to explicitly call the WidgetsFlutterBinding.ensureInitialized() first. which puzzles me, because I call WidgetsFlutterBinding.ensureInitialized() before runApp(). Anyway this method is not working.
    compute(computationFunction, 'argument');
    // ...
    static void computationFunction(String argument) async {
      await firstStepFunction();
    // ...
    
    • if I put my function into Isolate.spawn I get exception Unhandled Exception: Invalid argument(s): Isolate.spawn expects to be passed a static or top-level function which is also puzzling me. I tried to make the function static and moved the function to the top level of this fifth screen module. Nothing changed. Am I supposed to start the Isolate at the main function? In all beautiful examples it is done like that. Can't I start the Isolate in the middle by the button click.
    Isolate.spawn(computationFunction, receivePort.sendPort);
    // ...
    void computationFunction(SendPort sendPort) async {
      await firstStepFunction();
    // ...
    

    In Java I think a simple new Thread(...).start() will do the job.

    But how to do it in Flutter?


    Update:

    In my experiments I've noticed, that neither Flutter Hot Restart nor Hot Reload are not working correctly with isolates. You need really to run again the whole app.

    I managed to start Isolate.spawn all right if async/await keywords are removed. Off course the called function should have its synchronous version. So this does not work universally.

    Isolate.spawn(computationFunction, receivePort.sendPort);
    // ...
    static void computationFunction(SendPort sendPort) { // async removed
      firstStepFunctionSync(); // the function is replaced with its synchronous version 
    // ...
    

    I've found package flutter_isolate which allows to run the async functions:

    FlutterIsolate.spawn(computationFunction, argument);
    // ...
    void computationFunction(SendPort sendPort) async {
      await firstStepFunction();
    // ...
    

    I will try to use flutter_isolate package in my prototype.