I want to implement something like, when I tap on a download button, it will download the data from the API and store it in the database. Currently this code is working fine, though I haven't added any error handlers,
Suddenly, I noticed about Isolate.run
function, which does a lot of work in the back.
I want to replace this workable code with the Isolate.run
But I have no idea about how to do it.
Is this code good enough? If not, then which things I need to implement here?
I've a class Named, MyIsolate
, which is look like something,
class MyIsolate {
@pragma('vm:entry-point')
static Future<void> start(void Function(List<Object>) entryPoint,
RootIsolateToken token, int randomId, SendPort uiSendport) async {
final receivePort = ReceivePort();
final isolate = await Isolate.spawn(
entryPoint,
[receivePort.sendPort, token, randomId],
);
receivePort.listen((message) {
print('message $message');
if (message == 'done') {
print('done');
receivePort.close();
uiSendport.send('done');
isolate.kill();
}
});
}
}
From the UI, I'm using this like,
FloatingActionButton(
onPressed: () async {
//randomID between 1 and 10
final apiID = 1 + Random().nextInt(10 - 1);
receivePort = ReceivePort();
MyIsolate.start(
isolateEntryPoint,
RootIsolateToken.instance!,
apiID,
receivePort.sendPort,
);
//receivePort.asBroadcastStream()
receivePort.asBroadcastStream().listen((message) {
print('message in ui $message');
if (message == 'done') {
//show snackbar
receivePort.close();
}
});
},
tooltip: 'Download Background',
child: const Icon(Icons.download),
)
And this is my code that executes inside the Isolate,
void isolateEntryPoint(List<Object> args) async {
final SendPort sendPort = args[0] as SendPort;
final RootIsolateToken token = args[1] as RootIsolateToken;
final apiID = args[2] as int;
BackgroundIsolateBinaryMessenger.ensureInitialized(token);
// Make the network call with Dio
Dio dio = Dio();
Response response =
await dio.get('https://jsonplaceholder.typicode.com/users/$apiID');
DriftIsolate isolate;
// Parse the API response into Dart objects
final parsedData = UserDto.fromJson(response.data);
print(parsedData.toString());
DatabaseConnection connection = DatabaseConnection.delayed(() async {
isolate = await backgroundConnectionIsolate();
return await isolate.connect();
}());
MainDatabase db = MainDatabase.connect(connection);
UsersDAO dao = UsersDAO(db);
final response1 = await dao.insertUser(parsedData);
print(response1);
// Send the parsed data back to the main isolate
if (response1) {
sendPort.send(parsedData.toString());
} else {
sendPort.send(null);
}
//close
await connection.executor.close();
db.close();
sendPort.send('done');
}
I've tested with Isolate.run()
, but I can't understand how to pass the arguments, as it throws an error.
I also searched in ChatGPT. Maybe I'm not telling the ChatGPT in the proper way, how to do it.
In Isolate.spawn(), you pass arguments directly to the entry point. In Isolate.run(), you need to use closures to pass arguments. You encapsulate your function and its arguments within a closure and pass the closure to Isolate.run().
Modify the entry point for Isolate.run() by creating a closure that includes your original isolateEntryPoint function and its arguments. Ensure that your closure correctly handles the necessary operations and communication with the main isolate.
// Closure that includes your isolate entry point and its arguments
void Function() createIsolateFunction(SendPort sendPort, RootIsolateToken
token, int apiID) {
return () {
isolateEntryPoint(sendPort, token, apiID);
};
}
// Modified start method to use Isolate.run
static Future<void> startWithIsolateRun(
SendPort uiSendPort, RootIsolateToken token, int randomId) async {
final receivePort = ReceivePort();
final closure = createIsolateFunction(receivePort.sendPort, token,
randomId);
await Isolate.run(closure);
receivePort.listen((message) {
// Handle messages and potentially kill the isolate
});
}
// Usage
MyIsolate.startWithIsolateRun(receivePort.sendPort,
RootIsolateToken.instance!, apiID);
In this example, createIsolateFunction creates a closure that includes your original entry point and its arguments. This closure is then executed in a new isolate by Isolate.run().