尝试解释
我也发现该线程中的解决方法帖子的措辞非常混乱,我也无法完全理解它,但是发帖人似乎建议您使用setMockMessageHandler 来拦截数据来自invokeMethod。
setMockMessageHandler 覆盖处理函数,否则它将获取编码数据并将其传递到本机端,从而允许您使用自己的函数。因此,当您为通道设置模拟消息处理程序时,您可以“劫持”数据并通过 SendPort 将其传递回您的主隔离区。
在主隔离上获得消息后,您可以使用BinaryMessenger.send 将数据发送到其预期目的地。如果您在隔离区而不是主隔离区,这就是中断的步骤,所以现在您已经绕过了这个问题。
一旦您将数据接收回主线程,您就将其传递回隔离区,并使用您使用BinaryMessages.setMessageHandler 创建的自定义消息处理程序在那里对其进行解码。
解决方案包
如果您仍然需要它,我制作了一个包 (Isolate Handler),使用的解决方法与您询问的解决方法非常相似。
依赖setMockMessageHandler 的任何解决方法的缺点当然是您需要向它提供您将使用的频道名称。您可以通过查找 MethodChannels 的设置位置在源文件中找到这些频道名称。
似乎 sqflite 使用 com.tekartik.sqflite 而 path_provider 使用 plugins.flutter.io/path_provider,因此为了在 Isolate Handler 的隔离中使用它们,您需要执行以下操作:
IsolateHandler().spawn(
entryPoint,
channels: [
MethodChannel('com.tekartik.sqflite'),
MethodChannel('plugins.flutter.io/path_provider'),
]
);
void entryPoint(HandledIsolateContext context) {
final messenger = HandledIsolate.initialize(context);
// <Your previous isolate entry point here>
}
2019 年 9 月 4 日更新:
我最终通过从本机端开始隔离来为自己解决了这个问题。我从官方 Flutter 插件android_alarm_manager 中获得灵感。虽然该插件是特定于 Android 的,并且对于我的特定项目来说已经足够了,但可以在 iOS 中执行它,以及现在存档的 location_background_plugin 以及下面引用的 Medium 帖子中所示。
一位 Flutter 开发人员关于从本机端启动隔离的过程的非常全面(如果有点过于关注地理围栏)的帖子是 available on Medium。
帖子中采取的步骤总结:
- (GitHub) 使用
PluginUtilities.getCallbackHandle在 Dart 端设置一个引用回调调度程序的插件
- (GitHub) 创建回调调度程序本身,它:
- 初始化您要访问的 MethodChannel。
- 调用
WidgetsFlutterBinding.ensureInitialized() 设置MethodChannel 所需的内部状态。
- 在 MethodChannel(s) 上调用
setMethodCallHandler 以侦听来自插件本机端的后台事件,并在事件触发时调用您的回调。
- 最终使用
invokeMethod 提醒本机端插件回调处理程序已准备好处理事件。
- 实现本机代码以执行后台执行。
- 设置权限以允许后台作为服务执行。
- 安卓
- (GitHub) 使用 AndroidManifest.xml 将插件对象注册为服务。
- (GitHub) 创建自定义
FlutterActivity。
- (GitHub) 更新
AndroidManifest.xml中的application字段,设置为新创建的FlutterActivity。
- iOS
- (GitHub)。修改
Info.plist请求权限
- (GitHub) 从应用程序的
AppDelegate 设置对应用程序插件注册者的引用。
- (GitHub) 应用程序启动时在 Dart 端初始化插件(例如从
main。)
结论
这绝不是一个简单的解决方案,我仍然希望 Flutter 团队能提供一个更好的解决方案,但它至少是一个有效的解决方案,没有任何问题或意外行为。
我认为这是目前唯一可以投入生产的解决方案。