1. 介绍
数据存储属于ArkData(方舟数据管理)的一部分。ArkData除了提供数据存储的能力,也提供了数据管理和数据同步能力,比如联系人应用数据可以保存到数据库中,提供数据库的安全、可靠以及共享访问等管理机制,也支持与手表同步联系人信息。
我们这里先了解下数据存储,应用创建的数据库,存储的数据都是会保存到应用沙盒中,当应用卸载时,数据库也会自动删除。
在ArkData中,根据数据特点,数据持久化存储的方式有以下三种:
-
用户首选项(Preferences):
- 类似iOS的UserDefaults或者Android的SharedPreference,提供了轻量级配置数据的持久能力;
- 支持订阅数据变化的通知能力;
- 不支持分布式同步,常用于保存应用配置信息、用户偏好设置等;
- 会将文本中的数据全量加载到内存中,访问快,效率高,但不适合存储大量数据;
-
键值型数据库(KV-Store):
- 提供了键值型数据库的读写、加密、手动备份以及订阅通知的能力;
- 应用需要使用键值型数据库的分布式能力时,KV-Store会将同步请求发送给DatamgrService由其完成跨设备数据同步;
-
关系型数据库(RelationStore):
- 提供了关系型数据库的读写、加密、手动备份以及订阅通知的能力;
- 如果需要使用关系型数据库的分布式能力时,RelationalStore部件会将同步请求发送给DatamgrService由其完成跨设备数据同步
- 比如如果要在App内部存储复杂的数据结构,可以使用关系型数据库;
2.用户首选项
2.1 场景介绍
用户首选项为应用提供Key-Value键值型的数据处理能力,支持应用持久化轻量级数据,并对其修改和查询。其会将数据缓存放在内存中,当用户读取的时候,能够从内存中快速获取数据,当需要持久化的时候可以使用flush接口将内存中的数据写入持久化文件中。
为了提升数据读写效率,用户首选项会将所有数据存到内存,随着数据量越多,会导致应用占用的内存越大,因此不适合存放过多的数据,适用的场景一般为应用保存用户的个性化设置等。
2.2 运作机制
从下往上看,用户首选项也是以文件的形式存储到应用沙箱内的,开发者可以将用户首选项持久化文件的内容加载到Preferences实例(一个文件对应一个Preferences实例),系统会通过静态容器将该实例存储在内存中,直到主动从内存中移除该实例或者删除该文件。
对于Key和Value有一些限制:
- Key为string类型,非空且长度<=80个字节;
- Value为string时,长度<=8192个字节;
- 建议存储的数据不超过1万条;
2.3 接口说明
用户首选项和iOS的UserDefault,Android的SharedPreference的使用方法很像,都有基本的增、删、改、查方法,但不同的是用户首选项提供了订阅数据变更的能力:
// 获取Preferences实例。该接口存在异步接口。
getPreferencesSync(context: Context, options: Options): Preferences
// 将数据写入Preferences实例,可通过flush将Preferences实例持久化。该接口存在异步接口。
putSync(key: string, value: ValueType): void
// 检查Preferences实例是否包含名为给定Key的存储键值对。给定的Key值不能为空。该接口存在异步接口。
hasSync(key: string): void
// 获取键对应的值,如果值为null或者非默认值类型,返回默认数据defValue。该接口存在异步接口。
getSync(key: string, defValue: ValueType): void
// 从Preferences实例中删除名为给定Key的存储键值对。该接口存在异步接口。
deleteSync(key: string): void
// 将当前Preferences实例的数据异步存储到用户首选项持久化文件中。
flush(callback: AsyncCallback<void>): void
// 订阅数据变更,订阅的数据发生变更后,在执行flush方法后,触发callback回调。
on(type: 'change', callback: Callback<string>): void
// 取消订阅数据变更。
off(type: 'change', callback?: Callback<string>): void
// 从内存中移除指定的Preferences实例。若Preferences实例有对应的持久化文件,则同时删除其持久化文件。
deletePreferences(context: Context, options: Options, callback: AsyncCallback<void>): void
2.4 举例说明
// 导入包
import dataPreferences from '@ohos.data.preferences';
// 获取context
let context = getContext(this);
export default class PreferencesManager {
static shared = new PreferencesManager();
preferences?: dataPreferences.Preferences;
preferencesName: string = 'CommonPreferences';
// 初始化preferences实例
initPreferences() {
this.preferences = dataPreferences.getPreferencesSync(context, { name: this.preferencesName });
}
// 设置数据
set(key: string, value: dataPreferences.ValueType) {
if (!this.preferences) {
this.initPreferences();
}
this.preferences?.putSync(key, value);
this.preferences?.flush();
}
// 获取数据
get(key: string): dataPreferences.ValueType | null | undefined {
if (!this.preferences) {
this.initPreferences();
}
let value = this.preferences?.getSync(key, null);;
return value;
}
// 删除数据
delete(key: string) {
if (!this.preferences) {
this.initPreferences();
}
if (this.preferences?.hasSync(key)) {
this.preferences.deleteSync(key);
this.preferences.flush();
}
}
}
3. 键值型数据库
3.1 介绍
键值型数据库用于存储键值对形式的数据,适用于简单的存储场景:比如存储商品名称及对应价格、员工工号及今日是否已出勤等。
- 针对于单版本数据库,针对每条记录,Key的长度<=1KB,Value的长度<4MB;
- 设备协同数据库,针对每条记录,Key的长度<=896 Byte, Value的长度<4MB;
- 每个应用程序最多支持同时打开16个键值型分布式数据库;
- 键值型数据库事件回调方法中不允许进行阻塞操作,例如修改UI组件;
3.2 接口说明
键值型数据库相关的接口,大部分为异步接口,均有callback和Promise两种返回形式。
// 创建一个KVManager对象实例,用于管理数据库对象
createKVManager(config: KVManagerConfig): KVManager
// 指定Options和storeId,创建并得到指定类型的KVStore数据库
getKVStore<T>(storeId: string, options: Options, callback: AsyncCallback<T>): void
// 添加指定类型的键值对到数据库
put(key: string, value: Uint8Array|string|number|boolean, callback: AsyncCallback<void>): void
// 获取指定键的值
get(key: string, callback: AsyncCallback<Uint8Array|string|boolean|number>): void
// 从数据库中删除指定键值的数据
delete(key: string, callback: AsyncCallback<void>): void
3.3 举例说明
// 导入模块
import distributedKVStore from '@ohos.data.distributedKVStore';
// 获取context
let context = getContext(this);
export default class KVStoreManager {
// 单例模式
static shared = new KVStoreManager();
// SingleKVStore实例
KVStore?: distributedKVStore.SingleKVStore;
// 创建并获取KVStore
async initKVStore() {
try {
// Create KVManager
let bundleName = await getBundleName();
const kvManagerConfig: distributedKVStore.KVManagerConfig = {
context: context,
bundleName: bundleName
};
const manager = distributedKVStore.createKVManager(kvManagerConfig);
// Create KVStore
const options: distributedKVStore.Options = {
createIfMissing: true,
encrypt: false,
backup: false,
autoSync: false,
kvStoreType: distributedKVStore.KVStoreType.SINGLE_VERSION,
securityLevel: distributedKVStore.SecurityLevel.S1
};
this.KVStore = await manager.getKVStore<distributedKVStore.SingleKVStore>('storeId', options);
} catch (error) {
console.log('[KVStoreManager]', `Failed to initKVStore, Cause: ${error}`);
}
}
// 插入数据
async set(key: string, value: Uint8Array | string | number | boolean) {
if (!this.KVStore) {
await this.initKVStore();
}
try {
await this.KVStore?.put(key, value);
} catch (error) {
console.log('[KVStoreManager]', `Failed to set value, Cause: ${error}`);
}
}
// 获取数据
async get(key: string): Promise<string | number | boolean | Uint8Array | null | undefined> {
if (!this.KVStore) {
await this.initKVStore();
}
let value: Uint8Array | string | number | boolean | null | undefined = null;
try {
return this.KVStore?.get(key);
} catch (error) {
console.log('[KVStoreManager]', `Failed to get value, Cause: ${error}`);
}
return value;
}
// 删除数据
async delete(key: string) {
if (!this.KVStore) {
await this.initKVStore();
}
try {
await this.KVStore?.delete(key);
} catch (error) {
console.log('[KVStoreManager]', `Failed to delete value, Cause: ${error}`);
}
}
}
4. 关系型数据库
4.1 介绍
关系型数据库基于SQLite组件,适用于包含复杂关系数据的场景。比如购物车的商品数据,需要包括商品名称、价格、库存等。
基本概念:
- 谓词:用来定义数据库的操作条件;
- 结果集:执行查询之后的结果集合;
运作机制: 关系型数据库对应用提供通用的操作接口,底层使用SQLite作为持久化存储引擎,支持SQLite具有的数据库特性。
- 数据库同一时间只能支持一个写操作;
- ArkTS侧支持的基本数据类型:number、string、二进制类型数据、boolean;
- 为保证插入并读取数据成功,一条数据不要超过2M;
4.2 接口说明
// 获得一个相关的RdbStore,操作关系型数据库,用户可以根据自己的需求配置RdbStore的参数,然后通过RdbStore调用相关接口可以执行相关的数据操作
getRdbStore(context: Context, config: StoreConfig, callback: AsyncCallback<RdbStore>): void
// 执行包含指定参数但不返回值的SQL语句
executeSql(sql: string, bindArgs: Array<ValueType>, callback: AsyncCallback<void>):void
// 向目标表中插入一行数据
insert(table: string, values: ValuesBucket, callback: AsyncCallback<number>):void
// 根据RdbPredicates的指定实例对象更新数据库中的数据
update(values: ValuesBucket, predicates: RdbPredicates, callback: AsyncCallback<number>):void |
// 根据RdbPredicates的指定实例对象从数据库中删除数据
delete(predicates: RdbPredicates, callback: AsyncCallback<number>):void
// 根据指定条件查询数据库中的数据
query(predicates: RdbPredicates, columns: Array<string>, callback: AsyncCallback<ResultSet>):void
// 删除数据库
deleteRdbStore(context: Context, name: string, callback: AsyncCallback<void>): void
4.3 举例说明
// 导入模块
import relationalStore from '@ohos.data.relationalStore';
// 获取context
let context = getContext(this);
export default class RDBStoreManager {
private rdbStore: relationalStore.RdbStore | null = null;
private tableName: string;
private sqlCreateTable: string;
private databaseName: string = '__Database.db';
constructor(tableName: string, sqlCreateTable: string) {
this.tableName = tableName;
this.sqlCreateTable = sqlCreateTable;
}
// 创建rdbStore
async getRdbStore() {
if (!this.rdbStore) {
console.log('RDBStoreManager', 'The rdbStore exists.');
return
}
try {
let rdb = await relationalStore.getRdbStore(context, {
name: this.databaseName, // 数据库文件名
securityLevel: relationalStore.SecurityLevel.S1, // 数据库安全级别
encrypt: false // 可选参数,是否加密,默认不加密
});
this.rdbStore = rdb;
this.rdbStore.executeSql(this.sqlCreateTable);
} catch (error) {
console.log('RDBStoreManager', `gerRdbStore() failed, err: ${error}`);
}
}
// 插入数据
async insertData(data: relationalStore.ValuesBucket): Promise<number | null> {
const valueBucket: relationalStore.ValuesBucket = data;
if (this.rdbStore) {
try {
let result = await this.rdbStore.insert(this.tableName, valueBucket);
return result;
} catch (error) {
console.log('RDBStoreManager', `insertData() failed, err: ${JSON.stringify(error)}`);
}
}
return null;
}
// 删除数据
async deleteData(predicates: relationalStore.RdbPredicates): Promise<number | null> {
if (this.rdbStore) {
try {
let result = await this.rdbStore.delete(predicates);
return result;
} catch (error) {
console.log('RDBStoreManager', `deleteData() failed, err: ${error}`);
}
}
return null;
}
// 更新数据
async updateData(predicates: relationalStore.RdbPredicates, data: relationalStore.ValuesBucket): Promise<number | null> {
if (this.rdbStore) {
try {
let result = await this.rdbStore.update(data, predicates);
return result;
} catch (error) {
console.log('RDBStoreManager', `updateData() failed, err: ${error}`);
}
}
return null;
}
// 查询数据
async query(predicates: relationalStore.RdbPredicates): Promise<relationalStore.ResultSet | null> {
if (this.rdbStore) {
try {
let result = await this.rdbStore.query(predicates)
return result;
} catch (error) {
console.log('RDBStoreManager', `query() failed, err: ${error}`);
}
}
return null;
}
}
在以上3个举例说明中,是自己根据业务需求封装的工具类,在实际使用过程中还需要进行一些更改,仅作参考。
最后
鸿蒙开发正当时,现在入手正是好时机。
还在犹豫不决的朋友们,小编在这里建议大家早点入手!
在这里分享一份鸿蒙学习路线图帮助那些不知道怎么入门的朋友,另外一些鸿蒙开发的资料文档也顺便分享给大家,扫下方二维码就能免费送呢!
鸿蒙学习路线图
路线图适合人群:
- IT开发人员:想要拓展职业边界,享受新技术带来的溢价红利
- 零基础小白:鸿蒙爱好者,希望从0到1学习,增加一项技能
HarmonyOS 4.0 APP Developer
OpenHarmony 5.0 Next视音频
OpenHarmony 5.0 Next进阶
OpenHarmony 5.0 Next分布式
学习资料
内容概要:《鸿蒙零基础入门学习指南》、《鸿蒙开发学习之UI》、《鸿蒙开发学习之Web》、《鸿蒙开发学习之应用模型》
内容特点:条理清晰,含图像化表示更加易懂。
领取方式:扫描下方二维码即可免费领取!!!
《鸿蒙零基础入门学习指南》
一、快速入门
适用于HarmonyOS应用开发的初学者。通过构建一个简单的具有页面跳转/返回功能的应用,快速了解工程目录的主要文件,熟悉HarmonyOS应用开发流程。
- 开发准备
- 构建第一个ArkTS应用(Stage模型)
- 构建第一个ArkTS应用(FA模型)
- 构建第一个JS应用(FA模型)
二、开发基础知识
- 应用程序包基础知识
- 应用配置文件(Stage模型)
- 应用配置文件概述(FA模型)
三、资源分类与访问
应用开发过程中,经常需要用到颜色、字体、间距、图片等资源,在不同的设备或配置中,这些资源的值可能不同。
- 资源分类与访问
- 创建资源目录和资源文件
- 资源访问
四、学习ArkTs语言
ArkTS是HarmonyOS优选的主力应用开发语言。ArkTS围绕应用开发在TypeScript(简称TS)生态基础上做了进一步扩展,继承了TS的所有特性,是TS的超集。因此,在学习ArkTS语言之前,建议开发者具备TS语言开发能力。
- 初识ArkTS语言
- 基本语法
- 状态管理
- 其他状态管理
- 渲染控制
领取方式:扫描下方二维码即可免费领取!!!
《鸿蒙开发学习之UI》
一、方舟开发框架(ArkUI)概述
二、基于ArkTS声明式开发范式
- 1、UI开发(ArkTS声明式开发范式)概述
- 2、开发布局
- 3、添加组件
- 4、显示图片
- 5、使用动画
- 6、支持交互事件
- 7、性能提升的推荐方法
三、兼容JS的类Web开发范式
- 1、概述
- 2、框架说明
- 3、构建用户界面
- 4、常见组件开发指导
- 5、动效开发指导
- 6、自定义组件
领取方式:扫描下方二维码即可免费领取!!!
《鸿蒙开发学习之Web》
Web组件概述
使用Web组件加载页面
设置基本属性和事件
- 设置深色模式
- 上传文件
- 在新窗口中打开页面
- 管理位置权限
在应用中使用前端页面JavaScript
- 应用侧调用前端页面函数
- 前端页面调用应用侧函数
- 建立应用侧与前端页面数据通道
- 管理页面跳转及浏览记录导航
- 管理Cookie及数据存储
- 自定义页面请求响应
- 使用Devtools工具调试前端页面
ArkTS语言基础类库概述
并发
- 并发概述
- 使用异步并发能力进行开发
- 使用多线程并发能力
- 容器类库
- XML生成、解析、与转换
- 通知
窗口管理
- 窗口开发概述
- 管理应用窗口(Stage模型)
- 管理应用窗口(FA模型)
WebGL
- 概述
- WebGL开发指导
媒体
- 媒体应用开发概念
- 图片
安全
- 访问控制
- ohos.permission.USE_BLUETOOTH
- ohos.permission.DISCOVER_BLUETOOTH
- ohos.permission.MANAGE_BLUETOOTH
- ohos.permission.INTERNET
- ohos.permission.INTERNET
- …
网络与连接
- 网络管理
- IPC与RPC通信
电话服务
- 电话服务开发概述
- 跳转拨号页面
- 获取当前蜂窝网络信号信息
数据管理
- 数据管理概述
- 应用数据持久化
- 场景介绍
- 运作机制
- 约束限制
- 接口说明
- …
文件管理
- 文件管理概述
- 应用文件
- 用户文件
- 分布式文件系统
后台任务管理
- 后台任务总体概述
- 短时任务
- 长时任务
- 延时任务
- 代理提醒
设备管理
- USB服务
- 位置服务
- 传感器
- 分布式跟踪开发指导
- 错误管理
- …
国际化
- 国际化开发概述
- Intl开发指导
- I18n开发指导
应用测试
- 自动化测试框架使用指南
Native API相关指导
- Native API在应用工程中的使用指导
- Drawing开发指导
- Rawfile开发指导
- NativeWindow 开发指导
- …
领取方式:扫描下方二维码即可免费领取!!!
《鸿蒙开发学习之应用模型》
应用模型概述
- 应用模型的构成要素
- 应用模型解读
Stage模型开发指导
- Stage模型开发概述
- Stage模型应用组件
FA模型开发指导
- FA模型开发概述
- FA模型应用组件配置
- 进程模型
- 线程模型