状态管理¶
本节提供的是使用 Rinf 有效管理应用状态的一般性指南,而非介绍某个特定的 Rinf 功能。
当应用逻辑完全用 Rust 编写、Flutter 仅用作 GUI 时,Rinf 的表现最佳。基于此,希望将应用状态存储在 Rust 中。
Actor 模型¶
强烈推荐使用 Actor 模型来管理 Rust 中的异步状态。通过将状态和行为封装在 Actor 结构体中,这些结构体拥有了所有权并处理自身的异步任务,Actor 模型提供了一种可扩展且模块化的方式来管理复杂的状态交互。
Rinf 提供的默认 Rust 模板是一个很好的起点。下面是一个关于 Actor 如何工作的简短示例:
native/hub/src/lib.rs¶
use async_trait::async_trait;
use messages::prelude::{Actor, Address, Context, Notifiable};
use rinf::{dart_shutdown, debug_print, write_interface};
use tokio::spawn;
write_interface!();
/// 表示计算两个数之和的消息。
struct Sum(usize, usize);
/// Actor 定义,在实际应用中会持有状态。
struct MyActor {
count: i32,
}
impl Actor for MyActor {}
impl MyActor {
pub fn new() -> Self {
Self { count: 0 }
}
}
#[async_trait]
impl Notifiable<Sum> for MyActor {
async fn notify(&mut self, msg: Sum, _: &Context<Self>) {
self.count += 1;
debug_print!("{}: {}", msg.0 + msg.1, self.count);
}
}
fn create_actors() -> Address<MyActor> {
let context = Context::new();
let addr = context.address();
let actor = MyActor::new();
spawn(context.run(actor));
addr
}
/// 启动业务逻辑的主函数。
#[tokio::main]
async fn main() {
let mut addr = create_actors();
let _ = addr.notify(Sum(10, 5)).await;
dart_shutdown().await;
}
静态变量¶
一般来说,建议避免使用静态变量,因为其特性可能导致测试困难、生命周期管理不便等问题。如果必须使用静态变量,可以按如下方式声明,确保它们在整个应用运行期间有效。
Rust¶
use rinf::debug_print;
use tokio::sync::Mutex;
static VECTOR: Mutex<Vec<bool>> = Mutex::const_new(Vec::new());
pub async fn do_something_with_state() {
// 通过临时加锁来使用全局变量。
VECTOR.lock().await.push(true);
// 通过获取守卫来使用全局变量。
let guard = VECTOR.lock().await;
let length = guard.len();
debug_print!("{}", length);
}
仅在以下特定场景下使用静态变量,如 Rust 文档所述:
需要存储大量数据;
需要静态变量的单地址特性;
需要内部可变性。.
请务必注意,实现了 Drop trait 的静态变量的析构函数在应用关闭时不会被调用。因此,如果需要运行静态变量的析构函数,必须在退出前显式地释放或关闭它们。
还有一些替代方案,请根据需求选择您认为最合适的: