杨利杰YJlio博客头图

Preferences保存简单设置

大家好,我是杨利杰 YJlio。

上一节练习了表单校验。这一节我想解决另一个小问题:页面上的设置,怎样在关闭应用后再次读取?我选择一个启动模式,先完成读取、保存与重启核验的最小路径。

本篇编号025,计划日期2026年10月15日。原稿已保留;原稿的loadTickets返回空数组,只是持久化占位,并没有实现Preferences。下面补充真正调用接口的学习示例,尚未在本机编译或设备运行。所有配图均为概念示意。

一、先保存一个简单设置

本例只保存启动模式startup,允许manual与auto两个值。这是用于说明键值读写的练习字段,不会启动任何后台任务,也不创建工单。

Preferences适合轻量设置。本篇不把它当成工单列表查询方案;记录之间存在关系或需要条件查询时,应另外考虑数据模型与数据库方案。

简单设置用键值表示

二、名称、键与默认值固定下来

项目本例约定
Preferences实例名称settings
设置键startup
缺键默认值manual
保存练习值auto
合法取值manual、auto

名称用来定位实例,键用来定位其中的一项设置。后续读写都使用同一名称和同一键;改了名称或拼写,可能读到另一份数据,而不是之前保存的设置。

名称、键与默认值

三、把可用上下文传给存储函数

本例使用Stage模型中的UIAbilityContext作为函数参数。它应来自当前可用的Ability或页面宿主,不是一个自己拼出来的路径字符串。

import { preferences } from '@kit.ArkData';
import { common } from '@kit.AbilityKit';

async function openSettings(
  context: common.UIAbilityContext
): Promise<preferences.Preferences> {
  return await preferences.getPreferences(context, { name: 'settings' });
}

在UIAbility内部可以使用其this.context;从页面取宿主上下文时,则先核对当前SDK支持的方式与宿主类型。上面是存储函数,不是可以单独运行的完整页面。

getPreferences的参数与Promise重载已按官方接口文档核对;实际工程仍应匹配所选SDK。

先取得Preferences实例

四、put之后,等待flush完成

保存函数只接受两种启动模式:

type StartupMode = 'manual' | 'auto';

async function saveStartup(
  context: common.UIAbilityContext,
  mode: StartupMode
): Promise<void> {
  const store = await openSettings(context);
  await store.put('startup', mode);
  await store.flush();
}

本例未选择其他存储模式,按默认XML模式说明流程。put更新实例中的值,flush负责持久化。保存反馈要放在await saveStartup之后,不能只调用了put就宣称跨重启保存完成。

本例等待flush完成,再给出保存反馈;是否能跨重启读回仍需实际核验。

put之后再等待flush

五、读取默认值,再检查业务取值

async function loadStartup(
  context: common.UIAbilityContext
): Promise<StartupMode> {
  const store = await openSettings(context);
  const value = await store.get('startup', 'manual');
  if (value === 'manual' || value === 'auto') {
    return value;
  }
  throw new Error('启动模式值不合法');
}

默认值manual用于没有对应设置时的读取。接口也可能按类型规则回退默认值,不能把“读到了默认值”直接当作文件一定不存在。

本例不将任意字符串强制断言为StartupMode,而是检查两个合法值。如果旧数据中保存了其他字符串,就保留错误供排查。代码块属于同一组示例,import、openSettings与类型声明不需要在同一文件重复添加。

get读取并检查值

六、保存失败时,不显示成功

获取实例、put与flush都需要处理异常。下面的调用函数返回提示文字,由页面再赋给显示状态:

import { BusinessError } from '@kit.BasicServicesKit';

async function saveAndFeedback(
  context: common.UIAbilityContext
): Promise<string> {
  try {
    await saveStartup(context, 'auto');
    return '保存操作完成,请重启后核对';
  } catch (error) {
    const err = error as BusinessError;
    console.error(`saveStartup failed: ${err.code}, ${err.message}`);
    return '保存失败,请检查日志';
  }
}

错误分支不能被空catch吞掉。读取也需要调用方捕获失败;加载完成前不要让界面把未读取的默认显示误认为真实保存值。

如果页面允许重复点击,需在调用前设置忙碌状态、期间禁用操作,并在finally中恢复;本篇的存储函数没有实现整套页面按钮管理。

保存失败要保留错误

七、页面状态与持久化分开理解

页面中的@State用于显示和交互,Preferences用于保存这项设置。改变页面变量,不会自动调用put或flush;从存储读取成功后,也要将结果赋给页面显示状态。

这里限定单进程、小设置、默认XML模式。其他存储模式的落盘机制可能不同,不能把本例的flush说明扩展成所有模式的同一规则。关于模式与限制可参见官方持久化指南。

清除应用数据、卸载、修改实例名称或切换应用环境,不属于普通重启的同一条件;不要承诺这些操作之后设置仍然保留。

页面显示值、实例中的值和重启后的读回值,要分别留下观察记录。

页面状态不等于持久化

八、按同一个名称和键做重启核验

操作预期或检查内容当前状态
首次读取startup无已存值时按规则返回manual待实际验证
调用saveStartup保存auto等待put和flush完成待实际验证
同一应用内再次读取核对读回auto待实际验证
正常关闭后重新启动再次读取settings/startup,预期auto待实际验证
输入其他字符串的旧数据合法值检查应拒绝待实际验证
获取或写入失败保留日志,显示失败反馈待实际验证

重启核验时不清除应用数据,不换包或实例名称。记录实际DevEco Studio、SDK/API、设备与完整日志,写清正常重启与故障中断的区别。

同进程读回不能代替跨重启核验,示例预期也不能代替运行证据。

重启前后核对同一设置

写在最后

这一节我把原稿中的持久化占位改成了启动模式的读写示例:名称和键固定,保存等待flush,读取检查合法值,失败由调用方反馈。

这篇完成的是学习代码与观察路径整理,还没有真实SDK构建和重启结果。下一篇学习本地文件与应用沙箱,再继续区分设置、文件和业务记录的存储用途。

参考资料

  1. OpenHarmony官方文档:通过用户首选项实现数据持久化,用于核对默认存储模式与使用边界。
  2. OpenHarmony官方文档:用户首选项接口,用于核对getPreferences、put、get、flush;实际HarmonyOS工程以对应SDK文档为准。
  3. 本系列第025篇原稿:《使用Preferences保存简单设置》,计划日期2026-10-15。

声明:本文为个人学习笔记。代码与图片用于说明设置读写,尚未执行SDK编译或设备实测;保存完成与重启读回均需在实际工程验证。

结束分隔线

返回顶部

Logo

讨论HarmonyOS开发技术,专注于API与组件、DevEco Studio、测试、元服务和应用上架分发等。

更多推荐