app.rs
中首先定义了我们的TemplateApp
结构体
#[derive(serde::Deserialize, serde::Serialize)]
#[serde(default)]
pub struct TemplateApp {
label: String,
#[serde(skip)]
value: f32,
}
impl Default for TemplateApp {
fn default() -> Self {
Self {
label: "Hello World!".to_owned(),
value: 2.7,
}
}
}
- 在定义
TemplateApp
时,我们让其继承了serde::Deserialize, serde::Serialize
。serde
是rust中用于序列化和反序列化(serialize and deserialize)一个框架。详细见这里 - 在
eframe
中,我们使用的是ron
提供的序列化实现,与json
类似,但并不一致,例如以下是一个ron
序列化的结果:Scene( // class name is optional
materials: { // this is a map
"metal": (
reflectivity: 1.0,
),
"plastic": (
reflectivity: 0.5,
),
},
entities: [ // this is an array
(
name: "hero",
material: "metal",
),
(
name: "monster",
material: "plastic",
),
],
)
详细请参考https://github.com/ron-rs/ron - 看一个简单的
ron
序列化例子use serde::{Deserialize, Serialize};
#[derive(Debug, Deserialize, Serialize)]
struct MyStruct {
boolean: bool,
float: f32,
}
impl MyStruct {
fn new() -> Self {
return ron::from_str("(boolean: true, float: 1.23)").unwrap();
}
}
fn main() {
let x = MyStruct::new();
println!("RON: {}", ron::to_string(&x).unwrap());
}
- 关于更深层次的内容这里就不再展开了
(咱也展开不下去) 。
- 有了
serde
之后我们可以干什么呢?让我们继续看代码:impl TemplateApp {
pub fn new(cc: &eframe::CreationContext<'_>) -> Self {
if let Some(storage) = cc.storage {
return eframe::get_value(storage, eframe::APP_KEY).unwrap_or_default();
}
Default::default()
}
}
impl eframe::App for TemplateApp {
fn save(&mut self, storage: &mut dyn eframe::Storage) {
eframe::set_value(storage, eframe::APP_KEY, self);
}
- 首先我们为
TemplateApp
实现了new方法 - 而在之前的
main.rs
中,我们可以看到该方法的调用,实际上,该函数是在eframe
的各种准备工作完成后,才进行的回调eframe::run_native(
"demo app",
native_options,
Box::new(|cc| Box::new(demo_app::TemplateApp::new(cc))),
)
- 在该函数中,我们完成了一些状态数据的还原,即读取应用上一次的工作状态,那么这些数据又是在什么时候存储下来的呢?以及存在了哪里呢?
- 在接下来的代码中,我们实现了
eframe::App
特征,在save
方法中,我们对状态数据进行了存储,我们可以看看eframe::set_value
的具体实现:#[cfg(feature = "ron")]
pub fn set_value<T: serde::Serialize>(storage: &mut dyn Storage, key: &str, value: &T) {
match ron::ser::to_string(value) {
Ok(string) => storage.set_string(key, string),
Err(err) => log::error!("eframe failed to encode data using ron: {}", err),
}
}
- 我们可以运行一下应用看看效果,先修改输入:

关闭应用后再打开:

可以看到字符串确实保持一致,而数值已经变回原样了。 - 那我们的数据到底存储在哪里呢?参照上一节的做法,将
eframe
的日志输出打开,可以看到存储路径打印出来了[2023-08-19T09:26:27Z DEBUG eframe] Using the glow renderer
[2023-08-19T09:26:27Z DEBUG eframe::native::run] Entering the winit event loop (run_return)…
[2023-08-19T09:26:27Z DEBUG eframe::native::file_storage] Loading app state from "C:\\Users\\xxxx\\AppData\\Roaming\\demo app\\data\\app.ron"…
- 打开文件,可以看到存储的内容确实在,其中还存储了一些其他数据

- 当我们直接修改对应的数据后再打开应用,对应的数据也发生了变化:

- 既然是单个文件存储,那么是否会有竞争问题呢?我们打开两个应用A,B

A想要改字符串,B同时改了字符串和数值,B先关闭,A后关闭

再次打开应用,B修改的数据丢失了

因此在开发/使用的时候需要注意多窗口下的数据存储问题