A flutter package for Isolate code generation.
Features
- Warping your classes inside of
Isolate
and provide a new class with the same functionality that run inIsolate
. - Use all allowed dart types including streams
- Safe cross isolates with instance reference
Getting started
Add this package and build_runner to your dev_dependencies
flutter pub add --dev build_runner
flutter pub add --dev isolate_generator
you also need to add isolate_generator_annotation to your dependencies
flutter pub add isolate_generator_annotation
Usage
simply add GenerateIsolate
annotation to the classes you want to run inside of Isolate
import 'dart:ui';
import 'package:isolate_generator_annotation/isolate_generator_annotation.dart';
part 'image_isolate.g.dart';
@GenerateIsolate()
class MyClass {
int sum(int a, int b) {
return a + b;
}
Stream<int> streamRang({required int count}) async* {
for (var i = 0; i < count; i++) {
yield i;
}
}
}
run the code generator
flutter pub run build_runner build
and now you have generated MyClassIsolate
the usage is the same as the default class with minor difference
- you have
init
method which is used to initialize theIsolate
- you can get reference to the running
Isolate
byMyClassIsolate.isolate
- now
sum
method will returnFuture<int>
instead ofint
because isolate communications is asynchronous
using the generated class
final myClass = MyClassIsolate();
// initialize the isolate
await myClass.init();
// return a future int from the isolate
final sum = await myClass.sum(a, b);
// stream from the isolate
myClass.streamRang(count: 10).listen((event) {
print(event);
});
Generator arguments
isSameType
you can make the generated class identifiable as the default class
// true
MyClass() == MyClassIsolate();
this is useful in some cases, for example if you are targeting web with other platforms
to get this behavior change isSameType
to true
@GenerateIsolate(isSameType: true)
class MyClass {
...
}
this will tell the generated class to extend the default class and override it's methods
you need to make sure that all methods in the default class return
Future<T>
and/orStream<T>
to get the same behaviors from the generated class
sharedIsolate
if you want to run multiple classes in the same isolate while writing the code for each class in a separate file you can use sharedIsolate
argument
to use it all the classes should be in a library, to see the implementation take a look at shared_isolate_example
this isn't for communication between isolates but for sharing the same isolate between different class so you don't end up spawning different isolate for each simple class
Communications between isolates
to communicate between isolates simply use the genrated class with the new one you want to genrate, and that's it
@GenerateIsolate()
// the new class you want to run inside isolate
class MyNewClass {
// the generated class that already run inside an isolate
final genratedClass = MyClassIsolate();
Future<void> initMyClassIsolateIsolate() async {
//..your initialization code..//
await genratedClass.init();
}
Future<void> ss() async {
//..your logic..//
// invoke a method from this isolate on the other isolate
await genratedClass.createFile("fileName");
}
}
Whenever you call
genratedClass.init()
method in the main isolate or any other isolate If there is an already running isolate instance forgenratedClass
, it will be used instead of spawning a new isolate.
in case of communication between different classes that share the same isolate sharedIsolate
you can pass the instance through the constructor and annotate the class filed with FromIsolate
@GenerateIsolate(sharedIsolate: SharedIsolate(2, 2, "my_shared_isolate"))
class MySecoundClass {
// since this class will share the same isolate we can just pass the instance from the isolate
@FromIsolate()
final MyFirstClass first;
MySecoundClass(this.first);
int printValue(int n) {
// First is already running in the same isolate so we can use it directly
return first.calculate(n);
}
}
MyFirstClass
instance will be passed when initializing the isolate forMySecoundClass
, however you have to make sure that MyFirstClass
is initialized before using it in MySecoundClass
when you use
FromIsolate
annotation, even if you make the filed nullablefinal MyFirstClass? first
the instance will be passed inside the isolate so you don't have to pass it when initializing the genrated class when usingisSameType
Limitation
-
Have the same
Isolate
limitation -
the generator will only care about public functions/methods however you can use private functions and local variables internally without any issues
if you want to access local variable instance for example
class MyClass{
int val = 0;
}
in the above example you can't access val
from the generated class but you can use it internally, and if you want to access it make a function that return it
class MyClass{
int val = 0;
int getVal(){
return val;
}
}
now you can get val
in the generated class
final int myClass = MyClassIsolate();
await myClass.init();
final int val = await myClass.getVal();
Example app
The example directory has a sample application that uses this package.