无惧阻塞!Flutter从Rust丝滑接收Stream数据流

1,166 阅读4分钟

Flutter+Rust的最强组合实践之路(专栏)

如何用FRB(flutter_rust_bridge)快速搭建Flutter+Rust混编项目

关注专栏,一起学习。

在开发高性能、实时交互应用时,数据的高效传输与处理至关重要。 今天就来聊聊,如何让 Flutter 从 Rust 中丝滑接收 Stream 数据流,彻底告别阻塞烦恼!

01. 为什么需要 Flutter 从 Rust 接收 Stream 数据流?

在很多场景下,我们需要持续获取数据更新,比如实时聊天消息、股票价格变动、传感器数据采集等。 如果使用传统的单次数据传输方式,不仅效率低下,还可能导致数据丢失或延迟。 而 Stream 数据流就像一条源源不断的河流,能够持续、有序地将数据推送给接收方。

Rust 以其出色的性能和内存安全性,非常适合处理底层数据采集和复杂计算任务。 Flutter 则擅长构建精美、流畅的用户界面。 将两者结合,让 Rust 负责生产数据流,Flutter 负责展示数据,能充分发挥各自优势,打造出体验极佳的应用。

02. 案例说明

Rust 端:用文件系统API获取目录内容列表 Flutter 端:调用 Rust 函数并显示目录列表

在这个场景下,不同目录下的内容列表数量有非常大的差异,内容最少的是空目录,而多的可能高达上千甚至上万个项目。 这个区别导致调用同一个函数时,返回最终数据所需时间会随着目录内容项多少而产生很大浮动。 调用方如果每次调用都等待全部数据返回是不现实的,反映到界面上就是肉眼可见的卡顿或等待加载时间条。

Stream的机制可以完美解决这个问题,通过将数据流式传输,我们可以逐步接收目录内容,而不是等待所有数据一次性返回。 这样可以显著减少等待时间,提升用户体验。

03. 代码实践

本文依然基于Flutter Rust Bridge(FRB)这个库来实现 Flutter 与 Rust 的高效通信。 FRB 提供了一种简洁且高效的方式来桥接 Flutter 和 Rust,使得我们可以充分利用 Rust 的高性能和内存安全特性,同时结合 Flutter 强大的 UI 开发能力。

a. Rust端实现

Rust端我们采用文件系统模块std::fs的相关API来实现,通过参考FRB文档Stream数据处理章节,以下代码可以实现以Stream的形式读取并发送目录内容项:

首先定义一个目录内容项Struct,最终会转译成Dart的Class。

Pasted image 20250526140550.png

然后实现读取目录内容列表的函数

第一个参数传入泛型参数为上边FsEntity结构的StreamSink对象,StreamSink是FRB生成的胶水结构

第二个参数为Flutter端调用时需要传入的实际参数指定目录路径字符串

如函数无需关心返回值,设置为Result<()>,最后返回Ok(())即可

Pasted image 20250526140626.png

b. 执行FRB代码生成命令

在FRB生成的项目结构根目录下,执行

flutter_rust_bridge_codegen generate --watch

即可把上边的Rust代码Struct和函数转译出Flutter可以直接调用的API文件和代码。

Pasted image 20250526141617.png

可以看到,生成的代码中:

Struct对应Class, 生成的Dart函数稍微有点儿不同,Rust端函数里第一个参数StreamSink变成了Dart里的Stream成了返回值,其他参数没有变化成了Dart函数的关键字参数。

c. Flutter端代码

首先在组件类声明一个Stream流数据对象

late Stream<FsEntity> _fsEntitiesStream;

再调用Rust端转译的函数getFsEntities,更新State后,开启Stream订阅

var fsEntitiesStream = getFsEntities(rootPath: "D:\\somedir\\");
setState(() {  
  _fsEntitiesStream = fsEntitiesStream;  
});

_fsEntitiesStream.listen((evt) {  
  // 这里接收的evt即为Rust端代码以Stream流形式发送的FsEntity对象
  setState(() {  
    // 此处可以处理更新Widget数据State的值,通知对应界面元素更新显示。
    // ...
  });  
});

04. 总结

从案例实践可以看出,FRB作为Flutter和Rust的中间绑定层,对于业务层实现来说,提供了极大的便利和灵活性。 它不仅简化了跨语言通信的复杂性,还通过高效的数据传输机制,使得 Flutter 和 Rust 可以无缝协作。 这种协作方式在处理大量数据和高性能需求时,表现尤为突出。

本专栏专注Rust和Flutter深度协作实践,欢迎关注和交流。