So I basically have a simple class with a update() method. But because that update() method makes some math, I wanted to use compute() to make it run in another Isolate. The plan was to run the update() method in the Isolate and return the updated object like this:
compute(updateAsset, asset).then((value) => asset = value);
Asset updateAsset(Asset asset) {
asset.update();
return asset;
}
But then I get this error:
ArgumentError (Invalid argument(s): Illegal argument in isolate message : (object extends NativeWrapper - Library:'dart:ui' Class: Path))
Is there any possible way to send an object to an Isolate or do I have to send every single Value of that Asset as an Integer, create a new Object and return that?
The accepted answer is out of date now, there appears to be a lot more felexibility in what you can send in Flutter 3.7. The cookbook example says:
Isolates communicate by passing messages back and forth. These messages can be primitive values, such as null, num, bool, double, or String, or simple objects such as the List in this example.
You might experience errors if you try to pass more complex objects, such as a Future or http.Response between isolates.
The example code shows this:
Future<List<Photo>> fetchPhotos(http.Client client) async {
final response = await client
.get(Uri.parse('https://jsonplaceholder.typicode.com/photos'));
// Use the compute function to run parsePhotos in a separate isolate.
return compute(parsePhotos, response.body);
}
// A function that converts a response body into a List<Photo>.
List<Photo> parsePhotos(String responseBody) {
final parsed = jsonDecode(responseBody).cast<Map<String, dynamic>>();
return parsed.map<Photo>((json) => Photo.fromJson(json)).toList();
}
class Photo {
final int albumId;
final int id;
final String title;
final String url;
final String thumbnailUrl;
const Photo({
required this.albumId,
required this.id,
required this.title,
required this.url,
required this.thumbnailUrl,
});
factory Photo.fromJson(Map<String, dynamic> json) {
return Photo(
albumId: json['albumId'] as int,
id: json['id'] as int,
title: json['title'] as String,
url: json['url'] as String,
thumbnailUrl: json['thumbnailUrl'] as String,
);
}
}
It's a little unclear what they mean by "simple objects such as the List" - what is a simple object?
The docs shed a bit more light on it:
The transitive object graph of message can contain the following objects:
Null
bool
int
double
String
List, Map or Set (whose elements are any of these)
TransferableTypedData
SendPort
Capability
Type representing one of these types, Object, dynamic, void or NeverIf the sender and receiver isolate share the same code (e.g. isolates created via Isolate.spawn), the transitive object graph of message can contain any object, with the following exceptions:
Objects with native resources (subclasses of e.g. NativeFieldWrapperClass1). > A Socket object for example referrs internally to objects that have native resources attached and can therefore not be sent.
ReceivePort
DynamicLibrary
Finalizable
Finalizer
NativeFinalizer
Pointer
UserTag
MirrorReferenceApart from those exceptions any object can be sent. Objects that are identified as immutable (e.g. strings) will be shared whereas all other objects will be copied.
The send happens immediately and may have a linear time cost to copy the transitive object graph. The send itself doesn't block (i.e. doesn't wait until the receiver has received the message). The corresponding receive port can receive the message as soon as its isolate's event loop is ready to deliver it, independently of what the sending isolate is doing.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With