rust_in_flutter:用rust辅助开发flutter应用,支持跨平台桌面、安卓、iOS开发,性能优势

轻松集成 Rust 以使您的 Flutter 应用程序变得极快!

该软件包在设计时考虑了易用性、未来的可扩展性和卓越的性能,可处理幕后的所有复杂方面。只需将此包添加到您的 Flutter 项目中,您就可以编写 Rust 了!

好处

  • Rust 集成,能够使用任意数量的库箱
  • 不会弄乱敏感的构建文件,如CMake,Gradle,Podfile等
  • 在开发过程中无需生成复杂的代码
  • 定义无限的 RESTful API 端点,无需太多努力
  • 异步交互,来自 Dart 的简单请求和来自 Rust 的响应
  • 从 Rust 流向 Dart
  • 在 Dart 的热重启上重新启动 Rust 逻辑
  • 最小开销
  • 发送本机数据时没有内存副本

平台支持

所有具有挑战性的构建设置都由此包自动处理。请注意,Flutter 项目中的文件不受影响。

  • ✅ Linux:经过测试和支持
  • ✅ 安卓:经过测试和支持
  • ✅ 视窗:经过测试和支持
  • ✅ macOS:经过测试和支持
  • ✅ iOS:经过测试和支持
  • ⏸️ Web:不是现在,而是考虑

如果您有任何建议或想报告错误,请将其保留为问题拉取请求。我们将尽快做出回应。

为什么要使用 Rust?

虽然Dart是一种了不起的面向对象的现代语言,但它的性能有时不符合要求,因为它是非原生垃圾收集语言。这就是 Rust 发挥作用的地方。众所周知,Rust 的性能大约比 Dart 快 2~40 倍,更不用说利用多个线程的能力了。

👜 安装组件

基本步骤

首先,将此包添加到您的 Flutter 项目中。

flutter pub add rust_in_flutter

然后安装 Rust 工具链。请参考官方 Rust 文档

最后,检查您的系统是否已准备好进行编译。您可以在每个安装步骤后重复这些命令以验证系统状态。如果输出中没有问题,您就可以开始了!

rustc --version
flutter doctor

额外步骤

如果您打算为 Linux、Windows、macOS 或 iOS 编译代码,则无需执行任何其他步骤。

对于安卓,安装安卓 NDK 版本要求23.1.7779620

在 Rust 中使用额外的构建目标有时会带来各种问题。如果您遇到任何问题,请随时访问讨论页面并打开问答线程寻求帮助。

👜 应用模板

只需在 Flutter 项目文件夹的命令行中运行它即可。

dart run rust_in_flutter:apply_template

运行命令后,将有一些新的文件夹和文件将成为您的入门 Rust 模板。

    my_flutter_project/
    ├── android/
    ├── ios/
    ├── lib/
    ├── linux/
+   ├── native/
+   │   ├── hub/
+   │   │   ├── src/
+   │   │   └── Cargo.toml
+   │   ├── sample_crate/
+   │   │   ├── src/
+   │   │   └── Cargo.toml
+   │   └── README.md
    ├── web/
    ├── windows/
*   ├── .gitignore
+   ├── Cargo.toml
*   ├── pubspec.yaml
    └── ...

不要忘记先阅读文件。此外,您可能希望在生产中删除。./native/README.mdsample_crate

现在转到 ,您可以开始编写 Rust!./native/hub/src/lib.rs

🧱 技巧

从 Dart 请求时,应指定操作和地址。这种通信方式遵循 RESTful API 的定义。

import 'package:rust_in_flutter/rust_in_flutter.dart';
import 'package:msgpack_dart/msgpack_dart.dart';

void someFunction() async {
    var rustRequest = RustRequest(
      address: 'basicCategory.counterNumber',
      operation: Operation.Read,
      bytes: serialize(
        {
          'letter': 'Hello from Dart!',
          'before_number': 888,
          'dummy_one': 1,
          'dummy_two': 2,
          'dummy_three': [3, 4, 5]
        },
      ),
    );

    var rustResponse = await requestToRust(rustRequest);
    var message = deserialize(rustResponse.bytes) as Map;
    var innerValue = message['after_number'] as int;
}

收到来自 Rust 的请求后,您应该首先按地址对它们进行分类。

pub async fn handle_request(request_unique: RustRequestUnique) -> RustResponseUnique {
    let rust_request = request_unique.request;
    let interaction_id = request_unique.id;

    let layered: Vec<&str> = rust_request.address.split('.').collect();
    let rust_response = if layered.is_empty() {
        RustResponse::default()
    } else if layered[0] == "basicCategory" {
        if layered.len() == 1 {
            RustResponse::default()
        } else if layered[1] == "counterNumber" {
            sample_functions::calculate_something(rust_request).await
        } else {
            RustResponse::default()
        }
    } else {
        RustResponse::default()
    };

    RustResponseUnique {
        id: interaction_id,
        response: rust_response,
    }
}

在 Rust 中处理请求如下。此处定义了终结点消息架构,因为它因地址和操作类型而异。

pub async fn calculate_something(rust_request: RustRequest) -> RustResponse {
    match rust_request.operation {
        Operation::Create => RustResponse::default(),
        Operation::Read => {
            #[allow(dead_code)]
            #[derive(Deserialize)]
            struct RustRequestSchema {
                letter: String,
                before_number: i32,
                dummy_one: i32,
                dummy_two: i32,
                dummy_three: Vec<i32>,
            }
            let slice = rust_request.bytes.as_slice();
            let received: RustRequestSchema = from_slice(slice).unwrap();
            println!("{:?}", received.letter);

            let before_value = received.before_number;
            let after_value = sample_crate::add_seven(before_value);

            #[derive(Serialize)]
            struct RustResponseSchema {
                after_number: i32,
                dummy_one: i32,
                dummy_two: i32,
                dummy_three: Vec<i32>,
            }
            RustResponse {
                successful: true,
                bytes: to_vec_named(&RustResponseSchema {
                    after_number: after_value,
                    dummy_one: 1,
                    dummy_two: 2,
                    dummy_three: vec![3, 4, 5],
                })
                .unwrap(),
            }
        }
        Operation::Update => RustResponse::default(),
        Operation::Delete => RustResponse::default(),
    }
}

您可以扩展此 RESTful API 模式,并根据需要创建成百上千个端点。如果您有 Web 背景,则此系统可能看起来很熟悉。更多的注释和细节包含在 Rust 模板内的实际代码中。

理想情况下,Flutter 将处理跨平台用户界面,而 Rust 处理业务逻辑。前端和后端可以完全分离,这意味着 Dart 和 Rust 代码可以相互分离。这两个世界通过channels 和streams进行通信。

使用 MessagePack 序列化 Rust 模板提供的在 Dart 和 Rust 之间发送的消息,除非您有其他原因不这样做。对于那些不熟悉的人来说,MessagePack 是一种类似于 JSON 的嵌套二进制结构,但更快、更高效。

在 Dart 和 Rust 之间发送的数据基本上是字节数组,表示为 Dart 和 Rust。尽管建议使用 MessagePack 序列化,但您可以根据需要发送任何类型的字节数据,例如高分辨率图像或某种文件数据。

与Flutter+Rust技术类似的,是ReactNative+Rust开发移动APP,参考相关说明[2];使用React开发的Electron跨平台桌面应用方式,可参考相关说明[3]。

References:

[1] rust_in_flutter | Flutter Package (pub.dev)

[2] 与Flutter+Rust技术类似的,是ReactNative+Rust开发移动APP:网址

[3] 使用React开发的Electron跨平台桌面应用方式,参考wangzhi网址

版权声明:本文《rust_in_flutter:用rust辅助开发flutter应用,支持跨平台桌面、安卓、iOS开发,性能优势》为「linux名库」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。联系方式osschina@qq.com
 
Leave a Reply 0

Your email address will not be published. Required fields are marked *


加好友请备注:linuxlibs
您可以在微信公众号联系我们
您可以通过邮件联系我们
我们将24小时内回复。
取消