Flutter Isolate.run 使用多个参数

问题描述 投票:0回答:1

我想实现类似的功能,当我点击下载按钮时,它会从 api 下载数据并将其存储在数据库中。目前这段代码工作正常,尽管我没有添加任何错误处理程序, 突然,我注意到了一个

Isolate.run
函数,它在后面做了很多工作。

我想用 Isolate.run 替换这个可行的代码

但我不知道该怎么做。

这段代码是否足够好,如果不够好,那么我需要在这里实现哪些东西?

我有一个名为

MyIsolate
的课程,它看起来像什么,

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();
      }
    });
  }
}

来自

UI
我正在使用这个,

  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),
          )
        

这是我在隔离器内执行的代码,

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');
}

我已经使用

Isolate.run()
进行了测试,但无法理解如何传递参数,因为它会引发错误。 我也在GPT中搜索过,可能是我没有以正确的方式告诉GPT,该怎么做。

flutter dart background-process dart-isolates
1个回答
0
投票

在 Isolate.spawn() 中,您将参数直接传递到入口点。在 Isolate.run() 中,需要使用闭包来传递参数。您将函数及其参数封装在闭包中,并将闭包传递给 Isolate.run()。

通过创建包含原始isolateEntryPoint函数及其参数的闭包来修改Isolate.run()的入口点。 确保您的闭包正确处理必要的操作以及与主隔离的通信。

// 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);

在此示例中,createIsolateFunction 创建一个包含原始入口点及其参数的闭包。然后通过 Isolate.run() 在新隔离中执行此闭包。

© www.soinside.com 2019 - 2024. All rights reserved.