actors icon indicating copy to clipboard operation
actors copied to clipboard

Problems using with Flutter

Open synw opened this issue 5 years ago • 5 comments

Hi, sweet api. I tried it with Flutter and encountered number of problems: exceptions not thrown from actor, unreachable code errors when using with plugins, actor returning nothing. Is it compatible with Flutter?

Example code with path_provider, a common Flutter plugin, actor gets stuck:

class Two with Handler<int, dynamic> {
   handle(int i) async {
      var p = await getTemporaryDirectory();
      print("Found path: $p");
      return p;
   }
}

runActor() async {
   final actor = Actor(Two());
   print("SEND");
   var res = await actor.send(3).catchError((e) {
      print("ERROR: $e");
   }).then((res) {
      print("RES $res");
   });
   print('ok $res');
}

synw avatar Feb 28 '19 01:02 synw

Hi! I haven't had the time to use actors in Flutter, but pub says it's compatible. If you have problems it must be related to differences in Isolatebehaviour between DartVM and Flutter runtime. It could be the problems are simply related to AOT. I will try tonight and see if I can figure this out.

renatoathaydes avatar Feb 28 '19 06:02 renatoathaydes

Just tried:

dart --snapshot=run.snapshot --snapshot-kind=app-jit example/actors_example.dart
dart run.snapshot

Runs without problems... It seems the problem is only in Flutter... do you know if there's any issues with Isolates in Flutter?

renatoathaydes avatar Feb 28 '19 06:02 renatoathaydes

The code I provided does not even run in Flutter sorry, but at least it throws an exception: I've tested with their compute function.

After a bit of research it appears that isolates in Flutter can not access plugins neither run platform channel code inside. Also the data provided to the isolate has to be of native Dart type. All these limitations make the isolates in Flutter not very useful at the time.I hope they'll provide some more powerful primitives in the future for real concurrency: I miss Go here! Anyway keep on with your work, the api is great

synw avatar Feb 28 '19 13:02 synw

Ok, I will keep the issue open, so others can see it and not waste too much of their time because of this problem.

renatoathaydes avatar Feb 28 '19 17:02 renatoathaydes

Since Dart 2.15, it seems that Flutter now supports Isolates, hence actors, really well!

See this: https://dart.dev/guides/language/concurrency#sending-multiple-messages-between-isolates

Could any Flutter user please let me know if I can close this ticket?

renatoathaydes avatar Dec 28 '21 21:12 renatoathaydes

Hey there, just wanted to drop a note and say that I'm using actors successfully in a Flutter application. I am not using them across MethodChannels or anything too crazy, my usage is actually more geared at expensive operations done across thousands of entities which would cause jank without the use of background Isolates. A common usage is something like:

/// Returns a `Map` of [Transaction]s grouped by the [LocalDate] they occurred on.
class GroupByDateActor with Handler<List<Transaction>, Map<LocalDate, List<Transaction>>> {
  @override
  FutureOr<Map<LocalDate, List<Transaction>>> handle(List<Transaction> message) {
    // `groupedByDate` is just an extension method on `List<Transaction>` that runs a `fold` operation
    // that on large datasets could take ~50ms.
    return message.groupedByDate();
  }
}

/// Provides a [GroupByDateActor] for use by another [Provider]
final groupByDateActorProvider = Provider((ref) {
  final group = Actor.create(() => GroupByDateActor());
  ref.onDispose(() async => await group.close());
  return group;
});

// In another provider
final groupedByDateActor = ref.watch(groupByDateActorProvider);
final datesToTransactions = await groupedByDateActor.send(expenseTransactions);

This works great and has eliminated frame jank. What I'm struggling with (and which probably deserves its own issue) is the fact(s) that:

  1. Spinning up Isolates in debug mode seems to be extremely slow (though I haven't found any conversation on this (womp), so application launch/init is slower than I'd like. In release mode, it's just as fast as without using Isolates. I suspect there's some debugging overhead (like allowing setting breakpoints, etc.) associated with the each Isolate being spawned.

  2. Using Isolates during a flutter_test is painful, and oftentimes it's preferred to disable/opt out of Isolate usage. This is often done via a parameter into whatever component is using the background Isolate (as seen here in the constructor of this HTTP client). I would like to find a way to swap out my runtime (background -Isolate-using) Actors for "test Actors" that run their logic on the main Isolate.

EDIT: I've just discovered Messenger (thanks to a great README) which should allow me to do something like:

final groupByDateActorProvider = Provider<Messenger<List<Transaction>, Map<LocalDate, List<Transaction>>>>((ref) {
  // Using `Actor.of` is just a cleanup and removes the need for the separate `GroupByDateActor` class
  final actor = Actor.of(
    (List<Transaction> message) async => await message.groupedByDate(),
  );
  ref.onDispose(() async => await actor.close());
  return actor;
});

and then during tests (or even at runtime if I want to get fancy) can be overridden with:

groupByDateActorProvider.overrideWith((ref) {
  return LocalGroupByDate();
})

class LocalGroupByDate with Messenger<List<Transaction>, Map<LocalDate, List<Transaction>>> {
  @override
  FutureOr<void> close() {
    // Do nothing
  }

  @override
  FutureOr<Map<LocalDate, List<Transaction>>> send(List<Transaction> message) {
    return message.groupedByDate();
  }
}

btrautmann avatar Nov 21 '23 17:11 btrautmann

Thanks for the report @btrautmann ! I'm glad you found out you can test stuff without Isolates using the local messenger, that was basically why I made actors implement Messenger... but I am surprised Isolates are so slow on debug mode! I've never experienced that myself as I am not using Flutter much.

Anyway, closing this ticket as it seems actors works on Flutter well now.

renatoathaydes avatar Dec 16 '23 20:12 renatoathaydes