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