5.1 Preferences 键值存储


5.1 Preferences 键值存储

本节摘要:Preferences 是轻量键值存储:全量载入内存、毫秒级读取、异步落盘。本节实现一个重启后仍记得用户选择的设置页,并厘清 Preferences 与 PersistentStorage 的分工及使用纪律。

从两行代码的存储开始

需求很具体:设置页有个"深色模式"开关与"字号"滑条,用户下次打开应用时要恢复上次的值。这类数据的特点是——条目少(几十个以内)、整存整取(要的是"这一个键的值",不做条件查询)、读写频繁但量小。为它们建数据库表是杀鸡用牛刀,Preferences 正是为这个量级设计的。

基本用法三步:拿实例、写、读:

import { preferences } from '@kit.ArkData'; let store: preferences.Preferences | null = null; async function initStore(context: Context): Promise<void> { const options: preferences.Options = { name: 'mySettings' }; store = await preferences.getPreferences(context, options); } async function saveTheme(dark: boolean): Promise<void> { await store?.put('darkMode', dark); await store?.flush(); } async function loadTheme(): Promise<boolean> { return (await store?.get('darkMode', false)) as boolean; }

几个细节值得点破。getPreferences 的 name 参数对应沙箱内的一个文件,同 name 多次调用返回同一个实例(单例语义),不必缓存。put 只改内存,flush 才落盘——忘 flush 是新手丢数据的头号原因;反过来的坑是每次 put 都立刻 flush,高频写入时磁盘压力大,正确姿势是"一批修改一次 flush"(比如页面 onBackground 时统一落盘,正好接上第 2 章的生命周期)。get 的第二个参数是缺省值,键不存在时返回它,这让"首次启动"不需要特殊分支。

支持的值类型是基础类型:数值、布尔、字符串,够设置场景用;想存对象就序列化成 JSON 字符串,取回再解析——超过这个舒适区(列表、嵌套结构、要检索)就该换下一节的数据库。

把存储接进界面

只写工具函数不叫闭环,接到界面才算。设置页的完整骨架:

@Entry @Component struct SettingsPage { @State darkMode: boolean = false @State fontSize: number = 16 aboutToAppear(): void { this.darkMode = await loadTheme() this.fontSize = (await store?.get('fontSize', 16)) as number } build() { Column({ space: 20 }) { Row() { Text('深色模式').fontSize(16) Toggle({ type: ToggleType.Switch, isOn: this.darkMode }) .onChange(async (v: boolean) => { this.darkMode = v await saveTheme(v) }) } .width('100%') Row({ space: 12 }) { Text('字号').fontSize(16) Slider({ value: this.fontSize, min: 12, max: 28 }) .layoutWeight(1) .onChange(async (v: number) => { this.fontSize = Math.round(v) }) } .width('100%') } .padding(24) .onBackground(() => { void store?.flush() }) } }

两处设计说明。aboutToAppear 是组件的挂载回调,初始化读取放这里——这是第 2 章承诺过的"组件级生命周期"登场:进程级初始化在 onCreate(全应用一次),组件初始化在 aboutToAppear(每次进页面),两别混用。滑条的 onChange 高频触发,所以滑动过程只改 @State(界面实时预览),落盘收敛到 onBackground 统一 flush——正是"一批修改一次落盘"纪律的现场应用。

跑一遍验证:切换深色模式、拖字号、杀进程、重开——两个值都回来了。再做一个压力变式:把字号滑条的写盘改成 onChange 里立即 flush,用 Profiler 观察滑动期间的磁盘写入,对比收敛写法的差别。你会看到前者产生密集写调用——数据量小尚无感,但这个习惯放到高频场景就是事故种子。

与 PersistentStorage 的分工

第 4 章用过 PersistentStorage,它和 Preferences 什么关系?PersistentStorage 是"把 UI 状态自动接到持久化"的胶水:选定的 AppStorage 键自动落盘重启恢复,底层实现就是 Preferences。分工判据很清楚——要的是"状态"就 PersistentStorage(声明式、自动同步),要的是"数据"就手动 Preferences(控制精确、可批量管理生命周期)。同一个键两边都管是自找 race,团队里约定:UI 偏好走 PersistentStorage,业务数据走显式 Preferences 或数据库。

⚠️ 常见坑:把大字符串(如接口返回的整页 JSON、图片转义)塞进 Preferences。全量内存模型意味着每次启动都要把整个文件搬进内存,文件越大启动越慢。缓存类数据换数据库或文件,Preferences 只留"设置"。

💡 关键直觉:把 Preferences 当作用户偏好的抽屉,而不是数据库的低配版。判断标准就一条:这些数据你会写 SELECT 去查吗?会,就用数据库;不会,抽屉够用。

本节要点回顾:

  • 三步模型:getPreferences 拿单例、put 改内存、flush 落盘;忘记 flush 是头号丢数原因。
  • 缺省值:get 的第二参数让首次启动免特殊分支。
  • 类型边界:基础类型加 JSON 字符串;列表与检索需求到此为止。
  • 生命周期配合:读取在 aboutToAppear,批量落盘收敛在 onBackground。
  • 双轨分工:PersistentStorage 管状态自动持久化,Preferences 管数据显式管理,同键不共管。

设置这类轻数据已经拿下。当备忘录需要建表、按条件查、写事务保证一致性时,就轮到关系型数据库出场——下一节从建表语句写到增删改查闭环。


作者与出处
原作者: 灏天文库
来源:灏天文库
整理: 灏天文库整理
由灏天文库平台收录,内容或由平台用户上传,仅供学习交流
发布者: 作者: 灏天文库 转发
评论区 (0)
U