type
status
date
slug
summary
tags
category
icon
password
如何编写代码
📡 教程
来自 Dart 的请求,来自 Rust 的响应
假设你想创建一个新按钮,将一个数字数组和一个字符串从 Dart 发送到 Rust 以对其进行一些计算。您可以按照以下步骤了解如何发送请求并等待响应。
首先,在小部件树中创建一个
Column 位置。这将包含我们的教程小部件。创建一个
./messages 表示新 Rust 资源的新 .proto 文件。接下来,从
.proto 文件生成 Dart 和 Rust 消息代码。rinf message在 Dart 中创建一个接受用户输入的按钮小部件。
onPressed 函数应该向 Rust 发送请求。让我们创建一个 RustRequest 对象。requestToRust 函数将请求发送到 Rust,返回一个 RustResponse 对象。现在,编写我们的新端点 Rust 函数
sample_functions::handle_tutorial_resource 。这个简单的 API 端点将向数组中的每个元素添加一个,将字符串中的所有字母大写,然后返回它们。新的 Rust 资源的名称是
tutorial_resource 。确保 Rust 中的请求处理函数接受这一点。最后,当你在 Dart 中收到来自 Rust 的响应时,你可以用其中的字节数据做任何事情。
我们可以在命令行中看到打印的输出!
我们只是简单地在这里打印消息,但响应数据将用于重建 Flutter 小部件和更新真实应用程序中的状态。
您可以扩展此 RESTful API 模式,并根据需要创建成百上千个端点。如果您有网络背景,这个系统可能看起来很熟悉。
从 Rust 流式传输到 Dart
假设您希望每秒从 Rust 向 Dart 发送越来越多的数字。在这种情况下,Dart 重复发送请求是低效的。这是需要流媒体的地方。
让我们从默认示例开始。
定义 Rust 资源和消息模式。
从
.proto 文件生成 Dart 和 Rust 消息代码。rinf message定义一个永远运行的异步 Rust 函数,每秒向 Dart 发送一次数字。
在 Rust 中生成异步函数。
最后,在
StreamBuilder Dart 中接收信号,使用该 where 方法按资源过滤它们,然后重新构建 widget。我们在这里使用接收到的数据重新构建小部件,但流数据也可用于更新真实应用程序中的 Dart 状态。
🏷️ 消息详细信息
每个字段的含义
在本教程中,我们已经了解了如何在 Dart 和 Rust 之间传递
RustRequest 、 RustResponse 和 RustSignal 。现在让我们来看看每个字段的确切含义。resource:这是一个整数,指向适合您应用程序设计的虚拟 Rust 资源。始终提供ID由rinf message生成的一些消息模块。
operation:这接受枚举值,RustOperation并且可以是创建、读取、更新和删除之一,因为此系统遵循 RESTful API 的定义。
message:这是由 Protobuf 序列化创建的字节数组。请注意,不建议创建大于几兆字节的 Protobuf 消息。若要发送大型数据,请改用blob。发送字节数组是一个零拷贝操作,尽管 Protobuf 序列化和反序列化过程确实涉及内存复制。此字段是可选的,可以是null或None。
-
blob:这也是一个字节数组,旨在包含大数据,可能高达几千兆字节。您可以根据需要发送任何类型的二进制文件,例如高分辨率图像或某种文件数据。将 blob 从 Rust 发送到 Dart 是一个零拷贝操作,这意味着不涉及内存复制。相比之下,将 blob 从 Dart 发送到 Rust 是一个复制操作。此字段是可选的,可以是null或None。
响应超时
默认情况下,如果 Rust 在 60 秒内没有响应,Dart 将收到失败
RustResponse 的通知。要为您的 设置自定义超时,您可以选择为 requestToRust 函数提供超时参数 RustRequest ,如下所示:当你将 timeout 参数设置为
null 时,这意味着 Dart 将永远等待,直到它收到来自 Rust 端的响应。谨慎使用它很重要,因为如果 Rust 出于任何原因未能响应,Dart 将持续等待此事件,这可能会导致资源泄漏。效率
虽然 Rinf 的 API 系统可能类似于 Web 开发,但它仅依赖原生 FFI 进行通信。它不使用任何 Web 协议、隐藏线程和不必要的内存复制来防止任何性能开销。
📦 消息代码生成
Path 路径
当您使用该
rinf message 命令生成消息代码时,生成的 Dart 和 Rust 模块的名称和子路径将与 .proto 文件的名称和子路径精确对应。./messages: The.protofiles under here and its subdirectories will be used.
./messages :将使用此处及其子目录下 .proto 的文件。./lib/messages: The generated Dart code will be placed here.
./lib/messages :生成的 Dart 代码将放置在此处。./native/hub/src/messages: The generated Rust code will be placed here.
./native/hub/src/messages :生成的 Rust 代码将放置在此处。Continuous Watching 连续观看
如果将可选参数
-w 或 --watch 添加到命令中 rinf message ,则在修改文件时 .proto 将自动生成消息代码。如果添加此参数,则该命令不会自行退出。🖨️ 打印以进行调试
您可能习惯于在 Rust 中进行
println! 宏操作。然而,在我们用 Flutter 和 Rust 制作的应用程序中,使用该宏并不是一个好主意,因为在 println! Web 和移动模拟器上看不到输出。在
hub crate 中编写 Rust 代码时,您可以简单地使用该框架提供的 debug_print! 宏打印调试消息,如下所示。一旦你使用了这个宏,Flutter 将负责剩下的工作。debug_print! 也比 println! 它更好,因为它只在调试模式下工作,从而产生更小、更干净的发布二进制文件。🌅 优雅地关闭应用程序
当 Flutter 应用关闭时,Rust 端的整个
tokio 运行时将自动终止。但是,如果 Rust 端向 Dart 端发送消息,即使在 Dart VM 停止后,控制台中也会出现一些错误消息。为了防止这种情况,你可以在关闭 Flutter 应用之前调用 Rinf.ensureFinalized() Dart 来终止所有 Rust 任务。- Author:yaojunluo
- URL:https://next.yaojunluo.com/article/3f31c6b4-c6c8-4c78-a690-8e3b006ab981
- Copyright:All articles in this blog, except for special statements, adopt BY-NC-SA agreement. Please indicate the source!