程序员Feri  | 13年编程老炮,拆解技术脉络,记录程序员的进化史

一、先搞懂:首选项(Preferences)到底是什么?

首选项是 HarmonyOS 方舟数据管理(ArkData)里的「轻量级键值存储工具」,专门用来存 少量、简单的配置类数据

打个比方:你开发的 APP 里,用户设置的 “字体大小”“是否开启夜间模式”“上次登录的昵称”,这些数据量小、不用复杂查询,就适合用首选项存 —— 它像个 “小记事本”,把关键配置记下来,APP 下次打开还能读到。

它在 ArkData 体系里的定位很明确:「最轻量、最快」,和其他存储工具的区别一眼看清:

存储工具 核心优势 适合存什么 大概能存多少
首选项(本文) 速度快、用法简单 配置、开关、昵称等轻量数据 最多 100KB(单文件)
键值型数据库 支持加密、跨设备同步 稍多的业务数据(如购物车小项) 最多 10MB
关系型数据库 支持复杂查询(如 SQL) 大量关联数据(如订单、通讯录) 无明确上限

二、首选项的核心特点(一看就懂)

  1. 存储形式:以「键值对」存在设备的文本文件里(比如 “nightMode=true”“nickname = 小明”),文件存在 APP 的专属文件夹,其他 APP 读不到,安全。

  2. 加载速度:APP 打开时,会把整个文件加载到内存里 —— 所以读数据特别快,但如果数据太多(超过 100KB),会占内存,导致 APP 卡顿。

  3. 支持的数据类型:能存字符串(string)、数字(number)、布尔值(boolean)、日期(Date)等简单类型,不能直接存复杂对象(比如自定义的 “用户” 类,要转成 JSON 字符串才能存)。

  4. 持久化关键:修改数据后,要手动 “同步到磁盘”(调用flushSync()),不然只存在内存里,APP 崩溃或关闭后数据会丢。

三、手把手教你用首选项(步骤 + 代码)

原文的代码不变,这里按 “步骤 + 注意事项” 拆解,新手也能跟着做:

第一步:导入首选项模块

先把工具 “拿过来”,一行代码搞定:

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

👉 小提示:如果你的 APP 要兼容旧版本鸿蒙(API 8 及以下),要换成 import { preferences } from '@ohos.data.preferences'。

第二步:创建首选项实例(相当于打开 “记事本”)

要操作数据,得先创建一个实例(绑定一个文件,比如叫 “app_config”):

// 1. 配置文件信息(文件名:app_config,不用加后缀)
let option: preferences.Options = { name: "app_config" };
// 2. 创建实例(需要传入“上下文”,简单理解为APP的运行环境)
this.pre = preferences.getPreferencesSync(
  this.getUIContext().getHostContext(), // 上下文
  option
);

👉 关键注意:

  • 一定要加异常处理(防止文件创建失败,比如磁盘满了):

try {
  this.pre = preferences.getPreferencesSync(context, option);
} catch (err) {
  console.error("创建首选项失败:", err);
}
  • 一个文件名对应一个实例,APP 会自动缓存,不用重复创建。

第三步:增删改查数据(操作 “记事本”)

核心操作就 4 个,结合原文示例理解:

操作 代码示例 说明
存 / 改数据 pre.putSync("nickname", "小明") 键(nickname)存在就修改,不存在就新增
同步到磁盘 pre.flushSync() 必须调用!不然数据只在内存里
读数据 pre.getSync("nickname", "默认名") 没找到键就返回默认值
删除数据 pre.deleteSync("nickname") 删除后也要调用flushSync()才生效
读所有数据 pre.getAllSync() 返回所有键值对(比如 {nickname: "小明"})
完整示例(原文代码,带注释说明)
import { preferences } from '@kit.ArkData';

@Entry
@Component
struct Demo8 {
  pre?: preferences.Preferences; // 首选项实例
  inputValue: string = ''; // 输入框内容

  // APP页面渲染完成后执行(初始化实例)
  aboutToAppear(): void {
    try {
      let option: preferences.Options = { name: "study12" };
      this.pre = preferences.getPreferencesSync(
        this.getUIContext().getHostContext(),
        option
      );
    } catch (err) {
      console.error("实例化失败:", err);
    }
  }

  build() {
    Column({ space: 10 }) {
      Text("首选项演示")
      // 显示已存的“作者名”,默认值“默认”
      Text(this.pre?.getSync("author", "默认") + "")
      // 输入框:输入要存的内容
      TextInput({ placeholder: "请输入作者名" })
        .onChange(v => this.inputValue = v)
      // 按钮:保存输入的内容
      Button("修改作者名字")
        .onClick(() => {
          this.pre?.putSync("author", this.inputValue); // 存到内存
          this.pre?.flushSync(); // 同步到磁盘(关键!)
        })
    }
    .height('100%')
    .width('100%')
  }
}

四、进阶:封装工具类(不用重复写代码)

如果 APP 多个地方要用首选项,每次都写创建实例、存数据的代码太麻烦 —— 原文的工具类正好解决这个问题,这里说清楚 “怎么用”:

1. 工具类代码(原文不变,直接用)
import { preferences } from '@kit.ArkData';

// 封装好的工具类,直接导入就能用
export class PreferencesUtil {
  static preference: preferences.Preferences;

  // 初始化(只需要调用1次)
  static init(context: Context, dbname: string) {
    let option: preferences.Options = { name: dbname };
    PreferencesUtil.preference = preferences.getPreferencesSync(context, option);
  }

  // 检查是否存在某个键
  static checkKey(key: string): boolean {
    return PreferencesUtil.preference.hasSync(key);
  }

  // 读数据(没找到返回默认值)
  static get(key: string, defaultValue: string = ""): string {
    return PreferencesUtil.preference.getSync(key, defaultValue) as string;
  }

  // 存数据(自动同步到磁盘)
  static put(key: string, value: string) {
    PreferencesUtil.preference.putSync(key, value);
    PreferencesUtil.preference.flushSync();
  }

  // 删除数据
  static delete(key: string) {
    PreferencesUtil.preference.deleteSync(key);
    PreferencesUtil.preference.flushSync();
  }

  // 读所有数据
  static getAll(): Object {
    return PreferencesUtil.preference.getAllSync();
  }
}
2. 怎么用这个工具类?

两步走:

  • 第一步:在 APP 启动时初始化(只调用 1 次)

在EntryAbility的onCreate里初始化,确保 APP 一启动就准备好:

export default class EntryAbility extends UIAbility {
  onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {
    // 初始化首选项工具类,文件名叫“app_config.db”
    PreferencesUtil.init(this.context, "app_config.db");
  }
}
  • 第二步:在页面中直接用(不用再创建实例)

import { PreferencesUtil } from '../utils/PreferencesUtil';

@Entry
@Component
struct Demo9 {
  inputVersion: string = '';
  @State savedVersion: string = '';

  build() {
    Column({ space: 10 }) {
      TextInput({ placeholder: "请输入版本号" })
        .onChange(v => this.inputVersion = v)
      Button("存储版本号")
        .onClick(() => PreferencesUtil.put("version", this.inputVersion)) // 直接存
      Button("读取版本号")
        .onClick(() => this.savedVersion = PreferencesUtil.get("version")) // 直接读
      Text("已存版本号:" + this.savedVersion)
    }
    .height('100%')
    .width('100%')
  }
}

效果:

五、怎么验证数据真的存下来了?(测试方法)

按这两步测,确保持久化生效:

  1. 运行 APP,在输入框输入内容(比如 “1.0.0”),点击 “存储”;

  2. 关闭 APP(在模拟器里把 APP 划掉),重新打开;

  3. 点击 “读取”,如果能看到之前输入的 “1.0.0”,说明成功了!

六、避坑指南:这些错误别踩!

  1. 忘记调用flushSync():存了数据但没同步,APP 一关数据就丢;

  2. 存太多数据:超过 100KB 导致 APP 卡顿,这种情况换 “键值型数据库”;

  3. 实例化时没加try-catch:遇到磁盘满、文件名含特殊字符(比如 “/”“:”)会崩溃;

  4. 多地方重复创建实例:比如同一个文件创建多个实例,会占内存,甚至数据错乱;

  5. 存敏感数据:首选项不加密,密码、验证码等敏感信息别用它存(换 “键值型数据库” 并开启加密)。

七、最后:什么时候用首选项?什么时候换其他工具?

场景 选什么存储工具?
存字体大小、夜间模式、昵称 首选项(本文主角)
存购物车、收藏列表(稍多数据) 键值型数据库
存订单、通讯录(大量关联数据) 关系型数据库
存密码、Token(敏感数据) 键值型数据库(开启加密)
多设备同步数据(比如手机→手表) 键值型 / 关系型数据库

总而言之,HarmonyOS 首选项(Preferences)是专为轻量级键值数据设计的存储工具,以 “文本文件存储、全量加载内存” 为核心特点,适配 APP 个性化配置、简单状态记录等小数据量场景,凭借用法简洁、访问速度快的优势,成为开发中处理基础持久化需求的实用选择。

使用时需牢记 “修改后调用flushSync()同步磁盘”“单文件数据不超 100KB” 等关键要点,也可通过封装工具类提升复用效率;若遇到大量数据、敏感信息或跨设备同步需求,再按需切换至键值型或关系型数据库即可。

掌握首选项的适用边界与使用细节,能为鸿蒙应用开发的基础数据层打下扎实基础,助力高效实现各类轻量存储需求。

Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐