消息传递

您可以使用信号 trait 来将结构体标记为流端点。[1]

当您使用 rinf gen 命令从 Rust 结构体生成 Dart 信号类代码时,hub crate 会被分析,生成的 Dart 模块默认放置在 lib/src/bindings 文件夹中。

CLI
rinf gen

如果您为 rinf gen 命令添加可选参数 -w--watch,则当 Rust 文件被修改时,消息代码将自动生成。添加此参数后,命令效果不会自行退出。

CLI
rinf gen --watch

端点信号

RustSignal trait 生成从 Rust 到 Dart 的信号流。[2] 使用 RustSignalBinary trait 可包含二进制数据,而无需序列化的额外开销。

Rust
#[derive(Serialize, RustSignal)]
struct MyDataOutput {
  my_field: bool,
}
Rust
MyDataOutput { my_field: true }.send_signal_to_dart();
Dart
// 在每个渲染帧根据 Rust 信号重建 widget。
// 帧之间的一些 Rust 信号可能被忽略。
StreamBuilder(
  stream: MyDataOutput.rustSignalStream,
  builder: (context, snapshot) {
    RustSignalPack<MyDataOutput>? signalPack = snapshot.data;
    if (signalPack == null) {
      // 返回一个空 widget。
    }
    MyDataOutput message = signalPack.message;
    // 以下需要 `RustSignalBinary`。
    Uint8List binary = signalPack.binary;
    // 返回一个填充好的 widget。
  },
);

// 或者,处理每一个 Rust 信号。
// 别忘了在不再需要时取消订阅!
final subscription = MyDataOutput.rustSignalStream.listen((signalPack) {
  MyDataOutput message = signalPack.message;
})

// 您也可以获取从流中接收到的最新值。
// 这在构建和挂载新 widget 时很有用。
RustSignalPack<MyDataOutput>? latestSignal = MyDataOutput.latestRustSignal;

DartSignal trait 生成从 Dart 到 Rust 的信号流。使用 DartSignalBinary trait 可包含二进制数据,而无需序列化的额外开销。

Rust
#[derive(Deserialize, DartSignal)]
struct MyDataInput {
  my_field: bool,
}
Dart
MyDataInput(my_field: true).sendSignalToRust();
Rust
let receiver = MyDataInput::get_dart_signal_receiver();
while let Some(signal_pack) = receiver.recv().await {
  let message: MyDataInput = signal_pack.message;
  // 以下需要 `DartSignalBinary`。
  let binary: Vec<u8> = signal_pack.binary;
  // 自定义 Rust 逻辑写在这里。
}

现在让我们深入了解信号包每个字段的含义。

  • Field message: 表示由信号 trait 标注的类型的一条消息。此字段始终填充。

  • Field binary: 这是一个设计用于处理大型二进制数据的字段,可能达到数 GB。可以发送任何类型的二进制数据,例如高分辨率图像或文件数据。如果消息未标记为二进制信号,则此字段携带空的 Uint8ListVec<u8>

需要注意的是,不建议创建大于几兆字节的信号。对于大型数据,请将其拆分为多个信号,或改用 RustSignalBinaryDartSignalBinary trait 提供的 binary 字段。[3]

嵌套信号

要将结构体嵌套在信号结构体内部,要使用 SignalPiece trait。SignalPiece 不能独立地在语言之间传递,但可以嵌套在 RustSignalDartSignal 或另一个 SignalPiece 内部。

Rust
#[derive(Serialize, RustSignal)]
struct Outer {
  middle: Middle,
}

#[derive(Serialize, SignalPiece)]
struct Middle {
  inner: Inner,
}

#[derive(Serialize, SignalPiece)]
struct Inner {
  my_field: bool,
}