Flutter--Isolate问题记录

374 阅读1分钟

错误1:

Invalid argument(s): Illegal argument in isolate message: object is unsendable - Library:'dart:async' Class: _AsyncCompleter@4048458 (see restrictions listed at SendPort.send() documentation for more information)

错误2:

Bad state: The BackgroundIsolateBinaryMessenger.instance value is invalid until BackgroundIsolateBinaryMessenger.ensureInitialized is executed.

这两个问题应该放一起处理,先看问题1,复现场景,如下所示,看起来并没有明显参数类型错误

void onPressed() async {
    var receivePort = ReceivePort();
    await Isolate.spawn(gotoNext, [receivePort.sendPort]);
    final msg = await receivePort.first;
    print(msg);
  }

  void gotoNext(List<dynamic> args) {
    SendPort sendPort = args[0];
    log(args.toString());
    Isolate.exit(sendPort, "OK");
  }

其实Isolate 的回调方法应该是顶级函数static方法。所以你只需要改为

  static void runMyIsolate(List<dynamic> args) {
    var sendPort = args[0] as SendPort;
    print("In runMyIsolate ");
    Isolate.exit(sendPort, args);
  }

问题2简单,缺少了

var token = RootIsolateToken.instance!;

BackgroundIsolateBinaryMessenger.ensureInitialized(token);

所以这两个问题完整解决方案应该将Isolate.spawn相关方法抽离出来,放在最顶层

import 'dart:async';
import 'dart:isolate';
import 'package:flutter/services.dart';

Future<dynamic> computeIsolate(Future Function() function) async {
  final receivePort = ReceivePort();
  var rootToken = RootIsolateToken.instance!;
  await Isolate.spawn<_IsolateData>(
    _isolateEntry,
    _IsolateData(
      token: rootToken,
      function: function,
      answerPort: receivePort.sendPort,
    ),
  );
  return await receivePort.first;
}

void _isolateEntry(_IsolateData isolateData) async {
  BackgroundIsolateBinaryMessenger.ensureInitialized(isolateData.token);
  final answer = await isolateData.function();
  isolateData.answerPort.send(answer);
}

class _IsolateData {
  final RootIsolateToken token;
  final Function() function;
  final SendPort answerPort;

  _IsolateData({
    required this.token,
    required this.function,
    required this.answerPort,
  });
}

使用

var contacts = await computeIsolate(_run);

// 将你要执行的方法,作为静态方法添加到你的类,必须的
static Future<String> _run() async {
  return "Test";
}

参考 stackoverflow.com/questions/7…

stackoverflow.com/questions/7…