鸿蒙系统(HarmonyOS)提供了多样化的数据存储解决方案,覆盖从轻量级配置到复杂结构化数据、从内存临时存储到持久化存储、从单设备到分布式场景的各种需求。以下是所有存储方式的系统化总结。
一、鸿蒙系统主要数据存储方式
1. 按作用范围分类
类型 | 存储方式 | 作用范围 | 典型场景 |
---|---|---|---|
页面级 | LocalStorage | 单个页面或UIAbility内 | 页面状态共享 |
应用级 | AppStorage、PersistentStorage | 应用全局 | 全局状态管理 |
持久化 | Preferences、关系型数据库、KV-Store、文件存储 | 应用沙箱 | 数据持久保存 |
2. 按数据类型分类
类型 | 适用存储方案 | 特点 |
---|---|---|
键值对 | Preferences、KV-Store | 简单高效 |
结构化 | 关系型数据库 | 复杂查询 |
非结构化 | 文件存储 | 任意格式 |
状态数据 | LocalStorage、AppStorage | 内存共享 |
二、各存储方式详解与示例
1. LocalStorage
-
概念
LocalStorage是内存级的临时存储,数据仅在应用运行期间保留,应用退出后数据消失(非持久化) 。 - 作用范围:单个
@Entry
装饰的页面及其子组件,或通过绑定到UIAbility实现多个页面共享 。 -
与AppStorage的区别
- AppStorage是应用级全局存储,所有页面可访问;而LocalStorage是页面级存储,需显式传递实例或绑定到UIAbility才能跨页面共享 。
- LocalStorage的读写操作是同步阻塞的,频繁修改复杂对象可能影响性能 。
使用示例:
1、基本操作(逻辑层)
//基本操作
// 创建LocalStorage实例
let storage = new LocalStorage();
// 存储数据
storage.setOrCreate('key', 'value');
// 获取数据
let value = storage.get('key');
// 删除数据
storage.delete('key');
2. 在UI组件中绑定数据
通过装饰器@LocalStorageProp
(单向同步)或@LocalStorageLink
(双向同步)实现UI与LocalStorage的联动:
@Entry(storage) // 将LocalStorage实例传递给页面
@Component
struct MyPage {
@LocalStorageLink('key') linkValue: string = ''; // 双向同步
@LocalStorageProp('key') propValue: string = ''; // 单向同步
build() {
Column() {
Text(this.linkValue) // 修改会同步到LocalStorage
Text(this.propValue) // 修改仅本地生效
}
}
}
3. 跨页面共享数据
需在UIAbility中创建LocalStorage实例并绑定到窗口:
// UIAbility中初始化
onWindowStageCreate(windowStage: WindowStage) {
let storage = new LocalStorage();
windowStage.loadContent('pages/Index', storage); // 绑定到页面
}
// 其他页面通过getShared()获取实例
let sharedStorage = LocalStorage.getShared();
适用场景:
页面内组件的状态共享(如表单数据、临时筛选条件)。
UIAbility内多个页面的数据传递(需绑定到WindowStage)。
注意事项:
避免存储大量数据:LocalStorage是内存存储,可能影响应用性能 。
非持久化:如需长期保存,需结合PersistentStorage或数据库。
同步阻塞:频繁读写可能阻塞UI线程,建议简化操作 。
2. AppStorage
概念:AppStorage是内存中的全局存储,应用退出后数据不会保留。
特点:
- 全局可用,所有页面组件都能访问
- 数据存储在内存中,应用退出即消失
- 支持单向(@StorageProp)和双向(@StorageLink)绑定
使用示例:
// 初始化AppStorage
AppStorage.setOrCreate<string>('username', 'Jack');
// 在组件中使用
@Entry
@Component
struct MyComponent {
@StorageLink('username') username: string = '';
build() {
Column() {
Text(this.username)
.onClick(() => {
this.username = 'Tom'; // 修改会同步到AppStorage
})
}
}
}
适用场景:需要在多个页面间共享的临时数据。
3. PersistentStorage
概念:将AppStorage中的特定属性持久化到设备磁盘中。
特点:
- 应用退出后数据依然保留
- 实际上是AppStorage的持久化扩展
- 修改AppStorage会自动同步到PersistentStorage
- 支持基本类型和可JSON化的对象
使用示例:
// 持久化属性
PersistentStorage.persistProp<string>('theme', 'light');
// 之后可以通过AppStorage访问
@Entry
@Component
struct MyComponent {
@StorageLink('theme') theme: string = '';
build() {
Column() {
Text(`当前主题: ${this.theme}`)
.onClick(() => {
this.theme = (this.theme === 'light') ? 'dark' : 'light';
})
}
}
}
限制:
- 不支持嵌套对象(对象数组、对象的属性是对象等)
- 不支持undefined和null
- 建议存储小于2KB的数据
适用场景:需要持久化且全局访问的简单数据。
4. 首选项存储(Preferences)
概念:首选项存储是基于键值对的轻量级数据持久化方案,适合存储少量配置信息和用户偏好设置。
特点:
- 访问速度快,存取效率高
- 数据量应保持轻量级(建议不超过1万条)
- 数据保存在应用沙箱内部的文件中
- 仅支持本地存储
限制:
- Key为string类型,长度不超过80字节
- Value为string时,长度不超过8192字节(UTF-8编码)
使用示例:
// 导入首选项模块
import { preferences } from '@kit.ArkData';
// 1. 初始化首选项实例
const PREFERENCES_NAME = 'myPrefs';
const KEY_FONT_SIZE = 'fontSize';
const prefInstance = preferences.getPreferencesSync(getContext(), { name: PREFERENCES_NAME });
// 2. 写入数据
prefInstance.put(KEY_FONT_SIZE, 16); // 保存字体大小
prefInstance.flush(); // 持久化到磁盘
// 3. 读取数据
const fontSize = prefInstance.get(KEY_FONT_SIZE, 14); // 第二个参数为默认值
// 4. 删除数据
prefInstance.deleteSync(KEY_FONT_SIZE);
适用场景:登录账号密码、配置信息、字体大小、颜色主题等小型配置项。
5. 关系型数据库(RelationalStore)
概念:基于SQLite的关系型数据库,适合存储结构化数据。
特点:
- 支持完整的SQL语法
- 支持事务操作
- 适合大量结构化数据存储
- 底层使用SQLite引擎
使用示例:
import { relationalStore } from '@ohos.data.relationalStore';
// 1. 创建数据库
const config: relationalStore.RelationalStoreConfig = {
name: 'myDatabase.db',
version: 1
};
let store: relationalStore.RelationalStore;
relationalStore.getRdbStore(getContext(), config, (err, rdbStore) => {
store = rdbStore;
// 2. 创建表
const sql = `CREATE TABLE IF NOT EXISTS task (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL,
completed INTEGER DEFAULT 0)`;
store.executeSql(sql);
});
// 3. 插入数据
const insertSql = 'INSERT INTO task (name) VALUES (?)';
store.executeSql(insertSql, ['学习HarmonyOS']);
// 4. 查询数据
const querySql = 'SELECT * FROM task WHERE completed = ?';
store.query(querySql, [0], (err, resultSet) => {
// 处理结果集
});
适用场景:记账本、备忘录、复杂业务数据等需要关系型管理的场景。
6. 键值型数据库(KV-Store)
概念:分布式键值数据库,支持跨设备数据同步。
特点:
- 非关系型键值存储
- 支持分布式场景下的数据同步
- 适合业务关系简单的数据
- 比关系型数据库更轻量
使用示例:
import { distributedKVStore } from '@kit.ArkData';
// 1. 创建KVManager
const kvManagerConfig = {
context: getContext(),
bundleName: 'com.example.myapp'
};
const kvManager = distributedKVStore.createKVManager(kvManagerConfig);
// 2. 获取KVStore
const options = {
createIfMissing: true,
encrypt: true
};
kvManager.getKVStore('myStore', options, (err, kvStore) => {
// 3. 写入数据
kvStore.put('username', 'Alice');
// 4. 读取数据
const username = kvStore.get('username');
});
适用场景:需要跨设备同步的简单数据,如用户配置、游戏进度等。
7. 文件存储
概念:传统的文件系统存储,适合大文件和非结构化数据。
特点:
- 可以存储任意类型和大小的数据
- 需要处理文件路径和权限
- 应用数据存储在沙箱内
- 支持分布式文件共享
使用示例:
import file from '@ohos.file.fs';
// 写入文件
const path = '/data/accounts/account_0/appdata/com.example.myapp/files/data.txt';
file.writeText(path, 'Hello HarmonyOS', (err) => {
if (err) {
console.error('写入失败');
}
});
// 读取文件
file.readText(path, (err, data) => {
if (!err) {
console.log(data); // 输出: Hello HarmonyOS
}
});
适用场景:图片、音频、视频等媒体文件,或需要自由格式的大文本数据。
三、各存储方式对比
存储方式 | 作用范围 | 持久性 | 数据类型 | 适用场景 |
---|---|---|---|---|
LocalStorage | 页面/UIAbility内 | 非持久 | 任意可序列化数据 | 页面间临时状态共享 |
AppStorage | 全局 | 非持久 | 基本类型/简单对象 | 应用级全局状态管理 |
PersistentStorage | 全局 | 持久 | 基本类型/简单对象 | 简单持久化配置 |
首选项(Preferences) | 应用沙箱 | 持久 | 键值对 | 用户偏好设置、轻量配置 |
关系型数据库 | 应用沙箱 | 持久 | 结构化数据 | 复杂业务数据(如记账本) |
四、选择建议
- 少量配置数据:首选首选项存储,简单易用
- 全局临时数据:使用AppStorage
- 简单持久化数据:PersistentStorage是不错的选择
- 复杂结构化数据:必须使用关系型数据库
- 跨设备同步的简单数据:考虑KV-Store
- 大文件或非结构化数据:使用文件存储
鸿蒙系统的多种存储方案为开发者提供了灵活的选择,根据数据特点和应用场景选择最合适的存储方式,可以优化应用性能和用户体验。