无法理解“无法找到‘Window_sendPlatformMessage’(4 个参数)”错误的 Flutter Isolate 解决方法

A. *_*ine 1 plugins dart dart-isolates flutter

我正在将一个非常简单的标签打印应用程序转换为FlutterSwift。该应用程序的一个主要组件是本地缓存的数据库,用于离线访问产品。

虽然我可以在主线程上下载并缓存所有 12,000 多个产品,但对于如此繁重的操作来说,这是一个非常非常糟糕的解决方案,我真的很想避免这种情况,除非作为最后的手段。即使作为最后的手段,如果后台线程无法完成诸如将在线数据缓存到本地数据库等基本任务,我也很难说服雇主让我从 Swift 迁移到 Flutter。

因此,我一直在探索隔离。此过程中,每当"'Window_sendPlatformMessage' (4 arguments) cannot be found"尝试在. 现在我在githubstackoverflow上读到Isolates 不支持使用插件(可能是包?),除非以一种奇怪的解决方法。我尝试过一个插件,当我尝试使用它时,它只会使我的应用程序崩溃,并出现非常神秘的堆栈跟踪,因此看起来解决方法是唯一的方法。Isolate

我大约一周前才开始使用 flutter 进行构建,大约两天前才开始使用 Isolates,所以目前我对一切的基本了解还很肤浅。在 flutter 存储库上,有一条评论似乎概述了插件问题的解决方法,我希望它允许我使用path_providersqflite缓存从 Web API 获取的数据。

更有经验的 Flutter 开发人员能否为我将这个解释分解为婴儿咬伤?


编辑:

正如下面的答案中所述,sqflite它已经是异步的,并且显然在与主线程不同的线程上运行,因此看起来我的具体情况将通过使用计算来解决我的 dart-pure API 调用以获取 JSON 数据并使用常规sqflite用于存储。尽管如此,仍然需要一个关于不稳定的隔离解决方法的初学者指南,所以我将这个问题留待解决。

Kri*_*sta 5

尝试解释

\n\n

我也发现该线程中解决方法帖子的措辞非常令人困惑,我也无法真正完全理解它,但是海报似乎建议您使用setMockMessageHandlerinvokeMethod.

\n\n

setMockMessageHandler重写处理程序函数,否则该处理程序函数将获取编码数据并将其传递到本机端,从而允许您使用自己的函数。因此,当您为通道设置模拟消息处理程序时,您可以“劫持”数据并将其通过回传到SendPort主隔离。

\n\n

一旦您收到有关主要隔离的消息,您就可以使用BinaryMessenger.send数据发送到其预期目的地。如果您处于主隔离区以外的隔离区,则此步骤会中断,因此现在您已经绕过了该问题。

\n\n

一旦您将数据接收回主线程,您将其传递回隔离并使用您创建的自定义消息处理程序对其进行解码BinaryMessages.setMessageHandler

\n\n

解决方案包

\n\n

如果你还需要它,我做了一个包(Isolate Handler使用与您所询问的非常相似的解决方法

\n\n

当然,任何依赖的解决方法的缺点setMockMessageHandler是您确实需要为其提供您将使用的通道名称。您可以通过查找源文件中的位置来找到这些频道名称MethodChannels 的设置位置来在源文件中找到这些通道名称。

\n\n

看来sqflite使用com.tekartik.sqflite和path_provider使用plugins.flutter.io/path_provider,因此为了在具有 Isolate Handler 的隔离中使用它们,您将执行以下操作:

\n\n
IsolateHandler().spawn(\n    entryPoint,\n    channels: [\n      MethodChannel(\'com.tekartik.sqflite\'),\n      MethodChannel(\'plugins.flutter.io/path_provider\'),\n    ]\n);\n\nvoid entryPoint(HandledIsolateContext context) {\n  final messenger = HandledIsolate.initialize(context);\n  // <Your previous isolate entry point here>\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n
\n\n

2019-09-04 更新:

\n\n

我最终通过从本机端启动隔离来为自己解决这个问题。我从官方 Flutter 插件android_alarm_manager中获得了灵感。虽然该插件特定于 Android 并且对于我的特定项目来说已经足够了,但可以在 iOS 中执行此操作,如现已存档的location_background_plugin中所示以及下面引用的 Medium 帖子中所示。

\n\n

一位 Flutter 开发人员在 Medium 上发布了一篇非常全面(如果有点过于关注地理围栏)的帖子,介绍了从本机端启动隔离的过程

\n\n

帖子中采取的步骤摘要

\n\n
    \n
  1. ( GitHub ) 使用 Dart 端设置一个引用回调调度程序的插件PluginUtilities.getCallbackHandle
  2. \n
  3. ( GitHub ) 创建回调调度程序本身,其中:\n\n
      \n
    • 初始化您要访问的 MethodChannel。
    • \n
    • 调用WidgetsFlutterBinding.ensureInitialized()设置所需的内部状态MethodChannel
    • \n
    • 通话setMethodCallHandlerMethodChannel 来侦听来自插件本机端的后台事件,并在事件触发时调用回调。
    • \n
    • 最后提醒本机端插件回调处理程序已准备好使用事件invokeMethod.
    • \n
  4. \n
  5. 实现本机代码以执行后台执行。\n\n
  6. \n
  7. 设置权限以允许后台作为服务执行。\n\n
      \n
    • 安卓\n\n
        \n
      • ( GitHub ) 使用 AndroidManifest.xml 将插件对象注册为服务。
      • \n
      • ( GitHub ) 创建自定义FlutterActivity.
      • \n
      • ( GitHub ) 更新application中的字段AndroidManifest.xml,将其设置为新创建的FlutterActivity
      • \n
    • \n
    • iOS\n\n
        \n
      • GitHub)。调整Info.plist请求权限
      • \n
      • ( GitHub ) 设置对应用程序的 .xe2x80x99s 插件注册者的引用AppDelegate
      • \n
    • \n
  8. \n
  9. ( GitHubmain ) 当应用程序启动时(例如从.)初始化 Dart 端的插件
  10. \n
\n\n

结论

\n\n

这绝不是一个简单的解决方案,我仍然希望 Flutter 团队能够提供更好的解决方案,但它至少是一个有效的解决方案,不会出现任何问题或意外行为。

\n\n

我认为这是目前唯一可以投入生产的解决方案。

\n