我们在 ArkUI 开发中经常混淆两类存储:AppStorageLocalStorage属于内存临时存储,应用进程关闭后数据直接丢失,无法长久保存。 想要实现真正的数据持久化(关闭 App 再次打开数据仍然存在),就要使用鸿蒙官方持久化套件 ArkData。本文结合计算器项目「运算历史记录」需求,完整讲解 ArkData 三大存储方案、选型标准,并附带可运行实战代码。

一、什么是 ArkData

ArkData 是 HarmonyOS Stage 模型官方提供的本地磁盘持久化开发套件,数据写入设备磁盘,重启应用、重启手机数据不会丢失。 ArkData 提供三种独立存储方案,按需选择:

首选项 Preferences:轻量 Key-Value 键值存储

关系型数据库 RDB:支持 SQL 的结构化数据表

文件管理 File:直接操作沙盒原始文件

二、三种存储方案详解

import preferences from '@ohos.data.preferences';
import relationalStore from '@ohos.data.relationalStore';
import fs from '@ohos.file.fs';
import common from '@ohos.app.ability.common';

// 历史数据类型
interface CalcHistory {
  expr: string,
  result: string
}

1. 首选项 Preferences(键值存储)

存储结构:key-value 键值对,支持字符串、数字、布尔、数组等基础类型

优点:API 极简、上手快,无需设计数据表

短板:不适合海量数据、复杂关联查询

适用场景:应用配置、简易历史列表

let pref: preferences.Preferences;
const STORE_NAME = "calc_history";
const KEY_HISTORY = "history_list";

// 初始化
async function initPref(context: common.UIAbilityContext) {
  pref = await preferences.getPreferences(context, STORE_NAME);
}

// 写入历史数组
async function saveHistory(list: CalcHistory[]) {
  await pref.put(KEY_HISTORY, list);
  await pref.flush();
}

// 读取历史数组
async function loadHistory(): Promise<CalcHistory[]> {
  return pref.getSync(KEY_HISTORY, []);
}

2.关系型数据库 RDB

存储结构:标准数据表,支持 SQL 查询、分页、事务

优点:海量结构化数据、复杂筛选场景能力强大

短板:学习成本高,需要设计表结构

适用场景:聊天记录、商品清单、大量业务数据

const DB_NAME = "CalcDB";
const TABLE = "History";
let rdbStore: relationalStore.RdbStore;

// 初始化 & 创建表
async function initRdb(context: common.UIAbilityContext) {
  const config: relationalStore.StoreConfig = {
    name: DB_NAME,
    securityLevel: relationalStore.SecurityLevel.S1
  }
  rdbStore = await relationalStore.getRdbStore(context, config);
  // 创建数据表
  await rdbStore.executeSql(`CREATE TABLE IF NOT EXISTS ${TABLE}(id INTEGER PRIMARY KEY AUTOINCREMENT, expr TEXT, result TEXT)`);
}

// 新增一条记录
async function insertHistory(item: CalcHistory) {
  const valBucket: relationalStore.ValuesBucket = {
    expr: item.expr,
    result: item.result
  }
  await rdbStore.insert(TABLE, valBucket);
}

// 查询全部历史
async function queryAllHistory(): Promise<CalcHistory[]> {
  const resultSet = await rdbStore.query(TABLE, ["expr", "result"]);
  const list: CalcHistory[] = [];
  while(resultSet.goToNextRow()) {
    list.push({
      expr: resultSet.getString(0),
      result: resultSet.getString(1)
    })
  }
  resultSet.close();
  return list;
}

3.文件管理 File

存储结构:直接读写沙盒内文本、二进制文件

优点:自由度最高

短板:需要自己处理序列化、索引

适用场景:图片缓存、文档、自定义二进制资源

// 获取沙盒文件路径
function getFilePath(context: common.UIAbilityContext): string {
  return context.filesDir + "/history.json";
}

// 写入文件
async function saveHistoryByFile(context: common.UIAbilityContext, list: CalcHistory[]) {
  const path = getFilePath(context);
  const file = await fs.open(path, fs.OpenMode.CREATE | fs.OpenMode.WRITE_ONLY);
  await fs.writeText(file.fd, JSON.stringify(list));
  fs.close(file.fd);
}

// 读取文件
async function loadHistoryByFile(context: common.UIAbilityContext): Promise<CalcHistory[]> {
  const path = getFilePath(context);
  try {
    const content = await fs.readText(path);
    return JSON.parse(content) as CalcHistory[];
  } catch {
    // 文件不存在返回空数组
    return [];
  }
}

三、新手高频避坑知识点

1.ArkData:磁盘持久化,应用关闭数据依旧保留

2.LocalStorage / AppStorage:内存状态容器,进程销毁数据清空

正确业务架构思路(计算器项目):

运行时页面共享的历史列表存放在LocalStorage,

每次运算完成后,通过 ArkData 首选项写入磁盘,

页面启动时从磁盘读取数据载入内存。

两者相互配合,不可互相替代。

四、Preferences 实现计算器历史持久化

场景:保存计算器表达式 = 结果历史记录列表

首先导入模块

import preferences from '@ohos.data.preferences';
import common from '@ohos.app.ability.common';

// 定义单条历史数据结构
interface CalcHistory {
  expr: string,   // 表达式
  result: string  // 运算结果
}

// 首选项实例名称
const STORE_NAME = "calc_history_store";
// 存储历史列表使用的key
const HISTORY_KEY = "history_list";
let prefStore: preferences.Preferences | null = null;

1.初始化 Preferences(页面加载时执行)

async function initPreferences(context: common.UIAbilityContext) {
  try {
    prefStore = await preferences.getPreferences(context, STORE_NAME);
    console.info("首选项初始化成功");
  } catch (err) {
    console.error("初始化失败:", err);
  }
}

2. 读取本地保存的全部运算历史

async function getHistoryList(): Promise<CalcHistory[]> {
  if (!prefStore) return [];
  // 读取数组,默认空数组
  let list: CalcHistory[] = await prefStore.getSync(HISTORY_KEY, []);
  return list;
}

3. 新增一条运算历史,持久化写入磁盘

async function addHistoryItem(item: CalcHistory) {
  if (!prefStore) return;
  let list: CalcHistory[] = await getHistoryList();
  // 新记录插入最前面
  list.unshift(item);
  // 将更新后的列表存入首选项
  await prefStore.put(HISTORY_KEY, list);
  // 强制刷写到磁盘
  await prefStore.flush();
}

4. 清空全部历史记录

async function clearAllHistory() {
  if (!prefStore) return;
  await prefStore.put(HISTORY_KEY, []);
  await prefStore.flush();
}

5. 在计算器运算完成处调用示例

// 运算结束后执行保存
let newRecord: CalcHistory = {
  expr: "1+2*(3+5)",
  result: "17"
};
addHistoryItem(newRecord);

六、总结

ArkData 是鸿蒙应用本地持久化标准解决方案,三种存储各有定位,开发遵循够用原则。 像计算器历史、软件配置这类轻量数据,优先选择 Preferences; 同时理清架构思想:运行时状态交给 LocalStorage/AppStorage,持久化落地依靠 ArkData,二者分工协作,不要混淆使用。

Logo

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

更多推荐