{"id":23523992,"url":"https://github.com/rmawatson/flutter_isolate","last_synced_at":"2025-04-12T23:38:45.172Z","repository":{"id":41344732,"uuid":"170784888","full_name":"rmawatson/flutter_isolate","owner":"rmawatson","description":"Launch an isolate that can use flutter plugins.","archived":false,"fork":false,"pushed_at":"2024-09-12T14:25:52.000Z","size":215,"stargazers_count":287,"open_issues_count":48,"forks_count":84,"subscribers_count":4,"default_branch":"master","last_synced_at":"2025-04-12T23:38:41.094Z","etag":null,"topics":["dart","flutter","flutter-isolate","flutter-plugin"],"latest_commit_sha":null,"homepage":"","language":"Dart","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/rmawatson.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2019-02-15T01:46:13.000Z","updated_at":"2025-04-06T04:50:53.000Z","dependencies_parsed_at":"2023-01-22T14:30:12.357Z","dependency_job_id":"283eda6c-0be9-440c-9d6d-e3a9a67c1fe2","html_url":"https://github.com/rmawatson/flutter_isolate","commit_stats":{"total_commits":89,"total_committers":29,"mean_commits":"3.0689655172413794","dds":0.7303370786516854,"last_synced_commit":"8099e3e2bcb1c396a7619b7e2efcfd9c647567f4"},"previous_names":[],"tags_count":7,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rmawatson%2Fflutter_isolate","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rmawatson%2Fflutter_isolate/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rmawatson%2Fflutter_isolate/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rmawatson%2Fflutter_isolate/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/rmawatson","download_url":"https://codeload.github.com/rmawatson/flutter_isolate/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248647255,"owners_count":21139081,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["dart","flutter","flutter-isolate","flutter-plugin"],"created_at":"2024-12-25T18:13:18.189Z","updated_at":"2025-04-12T23:38:45.147Z","avatar_url":"https://github.com/rmawatson.png","language":"Dart","funding_links":[],"categories":[],"sub_categories":[],"readme":"# FlutterIsolate\n\nA Dart isolate is roughly equivalent to a single, independent execution thread. In a Flutter context, creating (\"spawning\") an isolate allows code to execute outside the main thread, which is important for running expensive/long-running tasks that would otherwise block the UI.\n\nHowever, code in a spawned isolate will generally not be able to interact with Flutter plugins. This is due to the tight integration between the platform plugin scaffolding and the main application isolate.\n\nThe FlutterIsolate plugin fixes this with the introduction of a `FlutterIsolate` class, which is a wrapper around the platform APIs for creating isolates and setting up the bindings necessary for code running in spawned isolates to communicate with Flutter plugins.\n\n### FlutterIsolate API\n\n|                  |      Android       |         iOS          |             Description            |\n| :--------------- | :----------------: | :------------------: |  :-------------------------------- |\n| FlutterIsolate.spawn(entryPoint,message)             | :white_check_mark: |  :white_check_mark:  | spawns a new FlutterIsolate        |\n| FlutterIsolate.pause()            | :white_check_mark: |  :white_check_mark:  | pauses a running isolate |\n| FlutterIsolate.resume()           | :white_check_mark: |  :white_check_mark:  | resumed a paused isolate |\n| FlutterIsolate.kill()             | :white_check_mark: |  :white_check_mark:  | kills a an isolate |\n| FlutterIsolate.killAll()             | :white_check_mark: |  :white_check_mark:  | kills all currently running  isolates |\n| FlutterIsolate.runningIsolates             | :white_check_mark: |  :white_check_mark:  | returns the IDs associated with all currently running isolates |\n| flutterCompute(callback,message)  | :white_check_mark: |  :white_check_mark:  | spawns a new FlutterIsolate, runs callback and returns the returned value |\n\n### Usage\n\nTo spawn a FlutterIsolate, call the `spawn` method with a top-level or static function that has been annotated with the `@pragma('vm:entry-point')` decorator:\n\n```dart\nimport 'package:flutter_isolate/flutter_isolate.dart';\n\n@pragma('vm:entry-point')\nvoid someFunction(String arg) { \n  print(\"Running in an isolate with argument : $arg\");\n}\n...\n\nclass SomeWidget() {\n...\n\n@override\n  Widget build(BuildContext context) {\n    return ElevatedButton(\n            child: Text('Run'),\n            onPressed: () {\n                FlutterIsolate.spawn(someFunction, \"hello world\");\n            },\n    );\n}\n```\n\n\nIf you just want to spawn an isolate to perform a single task (like the [Flutter `compute` method](https://api.flutter.dev/flutter/foundation/compute-constant.html)), call `flutterCompute`:\n```dart\n@pragma('vm:entry-point')\nFuture\u003cint\u003e expensiveWork(int arg) async {\n  int result;\n  // lots of calculations\n  return result;\n}\n\nFuture\u003cint\u003e doExpensiveWorkInBackground() async {\n  return await flutterCompute(expensiveWork, arg);\n}\n```\n\nIsolates can also be spawned from other isolates:\n\n\n```dart\nimport 'package:flutter_startup/flutter_startup.dart';\nimport 'package:flutter_isolate/flutter_isolate.dart';\n\n@pragma('vm:entry-point')\nvoid isolate2(String arg) {\n  FlutterStartup.startupReason.then((reason){\n    print(\"Isolate2 $reason\");\n  });\n  Timer.periodic(Duration(seconds:1),(timer)=\u003eprint(\"Timer Running From Isolate 2\"));\n}\n\n@pragma('vm:entry-point')\nvoid isolate1(String arg) async  {\n\n  final isolate = await FlutterIsolate.spawn(isolate2, \"hello2\");\n\n  FlutterStartup.startupReason.then((reason){\n    print(\"Isolate1 $reason\");\n  });\n  Timer.periodic(Duration(seconds:1),(timer)=\u003eprint(\"Timer Running From Isolate 1\"));\n}\n\nvoid main() async {\n  WidgetsFlutterBinding.ensureInitialized();\n\n  final isolate = await FlutterIsolate.spawn(isolate1, \"hello\");\n  Timer(Duration(seconds:5), (){print(\"Pausing Isolate 1\");isolate.pause();});\n  Timer(Duration(seconds:10),(){print(\"Resuming Isolate 1\");isolate.resume();});\n  Timer(Duration(seconds:20),(){print(\"Killing Isolate 1\");isolate.kill();});\n\n  runApp(MyApp());\n}\n...\n```\n\nSee [example/lib/main.dart](https://github.com/rmawatson/flutter_isolate/blob/master/example/lib/main.dart) for example usage with the [flutter_downloader plugin](https://pub.dev/packages/flutter_downloader).\n\nIt is important to note that the entrypoint must be a top-level function, decorated with the `@pragma('vm:entry-point') annotation:\n\n```dart\n@pragma('vm:entry-point')\nvoid topLevelFunction(Map\u003cString, dynamic\u003e args) {\n  // performs work in an isolate\n}\n\nclass MyApp extends StatefulWidget {\n  @override\n  _MyAppState createState() =\u003e _MyAppState();\n}\n\nclass _MyAppState extends State\u003cMyApp\u003e {\n\n  @override\n  void initState() {\n    FlutterIsolate.spawn(topLevelFunction, {});\n    super.initState();\n  }\n  Widget build(BuildContext context) {\n    return Container();\n  }\n}\n```\n\nor a static method:\n\n```dart\nclass MyApp extends StatefulWidget {\n  @override\n  _MyAppState createState() =\u003e _MyAppState();\n}\n\nclass _MyAppState extends State\u003cMyApp\u003e {\n  \n  @pragma('vm:entry-point')\n  static void topLevelFunction(Map\u003cString, dynamic\u003e args) {\n    // performs work in an isolate\n  }\n\n  @override\n  void initState() {\n    FlutterIsolate.spawn(_MyAppState.staticMethod, {});\n    super.initState();\n  }\n  Widget build(BuildContext context) {\n    return Container();\n  }\n}\n```\n\nA class-level method will *not* work and will throw an Exception:\n```dart\nclass MyApp extends StatefulWidget {\n  @override\n  _MyAppState createState() =\u003e _MyAppState();\n}\n\nclass _MyAppState extends State\u003cMyApp\u003e {\n\n  \n  void classMethod(Map\u003cString, dynamic\u003e args) {\n    // don't do this!\n  }\n\n  @override\n  void initState() {\n    \n    FlutterIsolate.spawn(classMethod, {}); // this will throw NoSuchMethodError: The method 'toRawHandle' was called on null.\n    super.initState();\n  }\n  Widget build(BuildContext context) {\n    return Container();\n  }\n}\n```\n\nFailure to add the `@pragma('vm:entry-point')` annotation will cause the app to crash in release mode.\n\n### Notes\n\nDue to a FlutterIsolate being backed by a platform specific 'view', the event loop will not terminate when there is no more 'user' work left to do and FlutterIsolates will require explict termination with kill().\n\nAdditionally this plugin has not been tested with a large range of plugins, only a small subset I have been using such as flutter_notification, flutter_blue and flutter_startup.\n\n### Communicating between isolates\n\nTo pass data between isolates, a ReceivePort should be created on your (parent) isolate with the corresponding SendPort sent via the `spawn` method:\n\n```dart\n@pragma('vm:entry-point')\nvoid spawnIsolate(SendPort port) {\n  port.send(\"Hello!\");\n}\n\nvoid main() {\n  var port = ReceivePort();\n  port.listen((msg) {\n    print(\"Received message from isolate $msg\");\n  });\n  var isolate = await FlutterIsolate.spawn(spawnIsolate, port.sendPort);\n\n}\n```\n\nOnly primitives can be sent via a SendPort - [see the SendPort documentation for further details](https://api.flutter.dev/flutter/dart-isolate/SendPort/send.html).\n\n\n### Custom plugin registrant\n\nSee the example project for a sample implementation using a custom plugin registrant.\n\n#### iOS\n\nBy default, `flutter_isolate` will register all plugins provided by Flutter's automatically generated `GeneratedPluginRegistrant.m` file.\n\nIf you want to register, e.g. some custom `FlutterMethodChannel`s, you can define a custom registrant:\n\n```swift\n// Defines a custom plugin registrant, to be used specifically together with FlutterIsolatePlugin\n@objc(IsolatePluginRegistrant) class IsolatePluginRegistrant: NSObject {\n    @objc static func register(withRegistry registry: FlutterPluginRegistry) {\n        // Register channels for Flutter Isolate\n        registerMethodChannelABC(bm: registry.registrar(forPlugin: \"net.myapp.myChannelABC\").messenger())\n\n        // Register default plugins\n        GeneratedPluginRegistrant.register(with: registry)\n    }\n}\n\n// In AppDelegate.swift\n@UIApplicationMain\n@objc class AppDelegate: FlutterAppDelegate {\n    override func application(\n        _ application: UIApplication,\n        didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?\n    ) -\u003e Bool {\n        let controller = window.rootViewController as! FlutterViewController\n\n        // Register custom channels for Flutter\n        registerMethodChannelABC(bm: controller.binaryMessenger) // \u003c-- the custom method channel\n\n        // Point FlutterIsolatePlugin to use our previously defined custom registrant.\n        // The string content must be equal to the plugin registrant class annotation \n        // value: @objc(IsolatePluginRegistrant)\n        FlutterIsolatePlugin.isolatePluginRegistrantClassName = \"IsolatePluginRegistrant\" // \u003c--\n\n        GeneratedPluginRegistrant.register(with: self)\n        return super.application(application, didFinishLaunchingWithOptions: launchOptions)\n    }\n}\n```\n\n#### Android\n\nDefine a custom plugin registrant, to be used specifically together with FlutterIsolatePlugin:\n\n```Java\npublic final class CustomPluginRegistrant {\n  public static void registerWith(@NonNull FlutterEngine flutterEngine) {\n    flutterEngine.getPlugins().add(... [your plugin goes here]);\n  }\n}\n```\n\nCreate a MainApplication class that sets this custom isolate registrant:\n```Java\npublic class MainApplication extends FlutterApplication {\n  public MainApplication() {\n    FlutterIsolatePlugin.setCustomIsolateRegistrant(CustomPluginRegistrant.class);\n  }\n}\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frmawatson%2Fflutter_isolate","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frmawatson%2Fflutter_isolate","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frmawatson%2Fflutter_isolate/lists"}