一、前言
本地持久化存储是鸿蒙App开发的核心刚需,所有商业化项目都离不开本地数据缓存。常见的用户Token、页面配置、个性化开关、离线缓存列表、本地日志、海量业务数据,都需要依靠本地存储实现持久化留存。
鸿蒙系统官方提供了三套成熟的本地存储方案:轻量键值存储 Preferences、原生文件存储、高性能关系型数据库 ArkDB。但绝大多数开发者都会出现选型混乱的问题:小数据用重型数据库、海量结构化数据用键值存储,最终引发页面卡顿、数据丢失、读写异常、内存泄漏、包体积增大等一系列线上Bug。
本篇文章将全方位拆解三种存储方案的特性、优缺点、适用场景,搭配可直接商用的完整源码、工具类封装、避坑指南与选型标准,帮你彻底搞定鸿蒙本地存储,适配所有商用项目开发。
二、三大存储方案核心选型对照表
先看懂选型逻辑,再动手写代码,是解决存储乱、性能差的核心关键。
存储方案 | 数据结构 | 读写性能 | 持久化能力 | 最佳适用场景 |
|---|
Preferences | Key-Value 键值对 | 小数据极速读写,大数据卡顿严重 | 永久持久化,轻量稳定 | 用户Token、主题设置、开关状态、基础配置、简单缓存 |
文件存储 | 文本/二进制文件 | 大文件读写优秀,结构化查询弱 | 永久持久化 | 图片缓存、日志文件、本地大JSON、音视频资源、离线文档 |
ArkDB 数据库 | 结构化数据表 | 海量数据增删改查高效,支持索引查询 | 永久持久化,支持事务 | 本地列表数据、订单数据、用户业务数据、多字段复杂数据 |
三、Preferences 轻量键值存储(实战封装)
3.1 核心特点
Preferences 是鸿蒙官方主推的轻量存储方案,无需手动创建文件,系统自动管理,读写速度快、API简单,专门用于存储少量配置类数据。
核心禁忌:禁止存储数组、对象、大量列表数据,会直接造成App卡顿、ANR。
3.2 工具类完整封装
新建工具类 common/PreferencesUtil.ets,全局统一读写、自动实例管理。
import preferences from '@ohos.data.preferences';import common from '@ohos.app.ability.common';let dataPreferences: preferences.Preferences | null = null;// 初始化Preferences实例export async function initPreferences(context: common.UIAbilityContext) { dataPreferences = await preferences.getPreferences(context, 'app_config');}// 存储数据export async function putData(key: string, value: preferences.ValueType) { if (!dataPreferences) return; await dataPreferences.put(key, value); await dataPreferences.flush();}// 获取数据export async function getData(key: string, defVal: preferences.ValueType) { if (!dataPreferences) return defVal; return await dataPreferences.get(key, defVal);}// 删除单条数据export async function deleteData(key: string) { if (!dataPreferences) return; await dataPreferences.delete(key); await dataPreferences.flush();}// 清空全部数据export async function clearAllData() { if (!dataPreferences) return; await dataPreferences.clear(); await dataPreferences.flush();}
3.3 页面调用示例
import { initPreferences, putData, getData } from './common/PreferencesUtil';import UIAbility from '@ohos.app.ability.UIAbility';@Entry@Componentstruct PreferencePage { async aboutToAppear() { // 初始化(建议在Ability中全局初始化一次) let context = getContext(this) as common.UIAbilityContext; await initPreferences(context); // 存储Token await putData('user_token', 'ABC123456789'); // 读取Token let token = await getData('user_token', ''); console.log('本地Token:', token); } build() { Column() { Text('Preferences 存储测试').fontSize(16) }.width('100%').height('100%') }}
四、原生文件存储(读写、缓存、日志实战)
4.1 适用场景
文件存储适合非结构化、大容量数据,比如日志文本、下载的图片、本地JSON大文件、缓存资源等,弥补Preferences无法存大数据的短板。
4.2 核心读写工具封装
import fs from '@ohos.file.fs';import common from '@ohos.app.ability.common';// 获取本地文件绝对路径export function getLocalFilePath(context: common.UIAbilityContext, fileName: string) { return context.filesDir + '/' + fileName;}// 写入文件export async function writeFile(context: common.UIAbilityContext, fileName: string, content: string) { let path = getLocalFilePath(context, fileName); let file = await fs.open(path, fs.OpenMode.CREATE | fs.OpenMode.WRITE_ONLY); await fs.write(file.fd, content); fs.close(file.fd);}// 读取文件export async function readFile(context: common.UIAbilityContext, fileName: string) { let path = getLocalFilePath(context, fileName); let file = await fs.open(path, fs.OpenMode.READ_ONLY); let content = await fs.readText(file.fd); fs.close(file.fd); return content;}
关键注意点:文件操作后必须手动 close 句柄,否则会造成文件句柄泄露、内存溢出。
五、ArkDB 数据库(海量结构化数据首选)
5.1 核心优势
ArkDB 是鸿蒙原生高性能关系型数据库,替代传统SQLite,支持事务、索引、增删改查,专门用于存储结构化、大批量、需要频繁查询修改的业务数据。
5.2 基础使用流程
初始化数据库实例
创建数据表
执行增删改查操作
关闭数据库、释放资源
5.3 极简实战示例
import relationalStore from '@ohos.data.relationalStore';import common from '@ohos.app.ability.common';const DB_NAME = 'user_db';const TABLE_NAME = 'user_list';const DB_VERSION = 1;// 初始化数据库export async function initDB(context: common.UIAbilityContext) { let config: relationalStore.StoreConfig = { name: DB_NAME, securityLevel: relationalStore.SecurityLevel.S1 } let store = await relationalStore.getRdbStore(context, config); // 创建用户表 await store.executeSql(` CREATE TABLE IF NOT EXISTS ${TABLE_NAME} ( id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT, age INTEGER ) `); return store;}
六、三大存储高频坑点汇总
Preferences 存大数据:大量循环读写、存储对象数组,直接导致页面卡顿、ANR崩溃;
文件不关闭句柄:多次读写不 close,造成文件锁占用、内存泄漏;
ArkDB 不释放实例:数据库反复创建不销毁,引发数据库卡死、读写失败;
数据硬编码存储:无版本兼容逻辑,App升级后本地数据全部丢失;
主线程读写大数据:阻塞UI线程,造成页面卡顿,所有持久化操作建议放子线程。
七、最终选型总结(项目标准)
配置类小数据(Token、开关、主题)→ 首选 Preferences
大容量非结构化数据(日志、图片、大文本)→ 首选 文件存储
结构化海量业务数据(列表、订单、用户数据)→ 首选 ArkDB
八、全文总结
本地存储是鸿蒙项目工程化的基础能力,没有万能的存储方案,合理选型、规范封装、资源释放是避免80%存储类Bug的核心。
本篇封装的三套存储工具类,完全适配API10+,开箱即用,可直接落地商用项目。统一的工具类封装,能彻底解决代码冗余、数据错乱、内存泄漏、卡顿崩溃等问题,大幅提升项目稳定性。