赞
踩
本文简单介绍了OpenHarmony持久化数据的几种方式
IDE:DevEco Studio 4.0 Release
SDK:3.2.13.5
模型:Stage
AppStorage 是运行在内存中的,应用一关闭数据不会保存。PersistenStorage 则可以持久化AppStorage中的属性,并且AppStorage中的更改都会自动同步到PersistenStorage 中。
接口名称 | 描述 |
---|---|
PersistProp<T>(key: string, defaultValue: T): void | 保存属性,若AppStorage不存在key,则使用defaultValue |
DeleteProp(key: string): void | 删除属性 |
PersistProps(properties: { key: string; defaultValue: any; }[]): void | 存储多个属性 |
Keys(): Array<string> | 获取属性名称列表 |
定义要持久化的属性以及默认值
PersistentStorage.PersistProp<string>('string', 'haha')
使用AppStorage获取属性 或者在组件中使用 @StorageLink
AppStorage.get('haha')
@StorageLink('string') str: string = 'hello world'
生成的持久化文件存储在 /data/storage/el2/100/base/xx.xx.xx/haps/xx/files/persistent_storage
中,以xml的格式存储
PersistentStorage.PersistProp 需要在 AppStorage访问属性(SetOrCreate,@StorageLInk)之前调用。如果反过来,就会出现上一次持久化的值被属性的默认值给覆盖掉了 。API9下 PersistentStorage只能在UI页面中使用
PersistentStorage 允许的类型有:number,string等简单类型,还有可以被 JSON.stringify
和JSON.parse
重构的对象。不支持嵌套对象,对象数组,undefined和null
观察aboutToAppear 方法的打印,发现应用关闭再打开后bool 和 person 的类型都变为了string。这就需要自己做判断转换类型了。尤其注意boolean类型,一不小心false变成'false',隐式转换成true(4.0已修改)
由于PersistentStorage 是立即同步,所以对于频繁修改的数据不建议使用,且持久化的变量最好小于2kb,否则会拖慢UI响应速度
首选项为用户提供Key-Value型数据处理能力,支持轻量级的数据持久化,并对其修改和查询。Perferences先将首选项文件加载到内存中,之后的操作都在内存中完成,直到调用flush方法才把内存中的数据写回到文件中去。
接口名称 | 描述 |
---|---|
getPreferences(context: Context, name: string): Promise | 获取Preferences实例。 |
put(key: string, value: ValueType): Promise; | 将数据写入Preferences实例,可通过flush将Preferences实例持久化。 |
has(key: string): Promise; | 检查Preferences实例是否包含名为给定Key的存储键值对。给定的Key值不能为空。 |
get(key: string, defValue: ValueType): Promise; | 获取键对应的值,如果值为null或者非默认值类型,返回默认数据defValue。 |
delete(key: string): Promise; | 从Preferences实例中删除名为给定Key的存储键值对。 |
flush(): Promise; | 将当前Preferences实例的数据异步存储到用户首选项持久化文件中。 |
on(type: ‘change’, callback: Callback<{ key : string }>): void | 订阅数据变更,订阅的Key的值发生变更后,在执行flush方法后,触发callback回调。 |
deletePreferences(context: Context, name: string): Promise; | 从内存中移除指定的Preferences实例。若Preferences实例有对应的持久化文件,则同时删除其持久化文件。 |
导入模块
import dataPreferences from '@ohos.data.preferences'
调用getPreferences获取实例,指定文件名称,文件不存在则会创建。获取实例成功时,可在回调中订阅数据变更事件
// 获取首选项实例,若没有则创建
dataPreferences.getPreferences(getContext(this), 'myPreference')
.then(data => {
console.info(TAG, 'success getPreferences')
this.preference = data
// 订阅数据变更事件
this.preference.on('change', key => {
// ...
})
})
.catch(err => {
console.error(TAG, `put error: ${JSON.stringify(err)}`)
})
对数据进行增删改查操作
Button('put').onClick((event: ClickEvent) => {
this.preference.put(this.input1, this.input2)
.then(() => {
console.info('put success')
})
.catch(err => {
console.error(TAG, `put error: ${JSON.stringify(err)}`)
})
})
Button('get').onClick((event: ClickEvent) => {
this.preference.get(this.input1, 'not found')
.then(data => {
console.info(`get: ${data}`)
console.info(TAG, data, typeof data)
})
.catch(err => {
console.error(TAG, `put error: ${JSON.stringify(err)}`)
})
})
Button('delete').onClick((event: ClickEvent) => {
this.preference.delete(this.input1)
.then(() => {
console.info('delete success')
})
.catch(err => {
console.error(TAG, `delete error: ${JSON.stringify(err)}`)
})
})

preferences模块需要调用flush方法,才会进行数据持久化操作
this.preference.flush()
.then(() => {
console.info('flush success')
})
.catch(err => {
console.error(TAG, `flush error: ${JSON.stringify(err)}`)
})
生成的持久化文件存储在 /data/storage/el2/100/base/xx.xx.xx/haps/xx/perferences/xxx
中,以xml的格式存储,且类型信息也存储了
put方法支持的类型有 number | string | boolean | Array<number> | Array<string> | Array<boolean>
preferences 模块是将数据加载到内存中去,所以建议存储数据不超过一万条。否则就应该考虑用数据库来进行存储
键值型数据库存储键值型的数据,支持单版本数据库和设备协同数据库两种。
每个应用程序最多同时打开16个键值型数据库,设备协同数据库健长度<=896Byte,单版本数据库健长度<=1KB,Value的长度均小于4MB
接口名称 | 描述 |
---|---|
createKVManager(config: KVManagerConfig): KVManager | 创建一个KVManager对象实例,用于管理数据库对象。 |
getKVStore(storeId: string, options: Options): Promise; | 指定Options和storeId,创建并得到指定类型的KVStore数据库。 |
put(key: string, value: Uint8Array | string | number | boolean): Promise; | 添加指定类型的键值对到数据库。 |
get(key: string): Promise<boolean | string | number | Uint8Array>; | 获取指定键的值。 |
delete(key: string): Promise; | 从数据库中删除指定键值的数据。 |
getEntries(keyPrefix: string): Promise<Entry[]> | 获取匹配指定前缀的所有键值对 |
导入模块
import distributedKVStore from '@ohos.data.distributedKVStore';
获取KVManager实例,用于管理数据库对象
// KVManager配置信息
const config: distributedKVStore.KVManagerConfig = {
context: getContext(this), // 上下文信息
bundleName: 'com.example.storedemo' // 所属应用
}
// 创建KVManager
const manager = distributedKVStore.createKVManager(config)
获取数据库实例
// 数据库配置信息
const options: distributedKVStore.Options = {
createIfMissing: true, // 数据库不存在时是否创建,默认true
encrypt: false, // 数据库文件是否加密,默认false
backup: false, // 数据库问价你是否备份,默认false
autoSync: false, // 是否自动同步,默认false
// 数据库类型:分布式数据库或单版本数据库,默认分布式数据库
kvStoreType: distributedKVStore.KVStoreType.SINGLE_VERSION,
// 数据库安全级别
securityLevel: distributedKVStore.SecurityLevel.S1,
}
// 创建数据库
manager.getKVStore<distributedKVStore.SingleKVStore>('myKvStore', options)
.then(kvStore => {
console.info('getKVStore success')
this.database = kvStore
})
.catch(err => {
console.error(TAG, `getKVStore failed: ${JSON.stringify(err)}`)
})

对数据库进行增删改查操作
Button('put').onClick((event: ClickEvent) => {
this.database.put(this.input1, this.input2)
.then(() => {
this.showToast('put success')
})
.catch(err => {
console.error(TAG, `put error: ${JSON.stringify(err)}`)
})
})
Button('get').onClick((event: ClickEvent) => {
this.database.get(this.input1)
.then((data) => {
this.showToast(`get: ${data} ${typeof data}`)
})
.catch(err => {
console.error(TAG, `get error: ${JSON.stringify(err)}`)
})
})
Button('delete').onClick((event: ClickEvent) => {
this.database.delete(this.input1)
.then(() => {
this.showToast('delete success')
})
.catch(err => {
console.error(TAG, `delete error: ${JSON.stringify(err)}`)
})
})

生成的持久化文件存储在 /data/app/el2/100/database/xx.xx.xx/xx/kvdb/xxx(sortedId)/single_ver/main
中,信息已经做了加密处理。
如果想要查看数据库文件,需要把这三个文件都拷贝出来放在同一文件夹下,用sqlite客户端工具打开。拷贝命令:hdc file recv srcPath targetPath
关系型数据库基于sqlite组件,适合存储一些复杂的数据关系,支持执行sql 语句。
存储复杂关系时使用,比如学生信息(姓名,学号,班级等),班级信息(班级名称,班主任名称等)。支持事务,最多同时持有4个数据库连接。
接口名称 | 描述 |
---|---|
getRdbStore(context: Context, config: StoreConfig): Promise; | 获得一个相关的RdbStore,操作关系型数据库,用户可以根据自己的需求配置RdbStore的参数,然后通过RdbStore调用相关接口可以执行相关的数据操作。 |
executeSql(sql: string, bindArgs?: Array): Promise; | 执行包含指定参数但不返回值的SQL语句。 |
insert(table: string, values: ValuesBucket): Promise; | 向目标表中插入一行数据。 |
update(values: ValuesBucket, predicates: RdbPredicates): Promise; | 根据RdbPredicates的指定实例对象更新数据库中的数据。 |
delete(predicates: RdbPredicates): Promise; | 根据RdbPredicates的指定实例对象从数据库中删除数据。 |
query(predicates: RdbPredicates, columns?: Array): Promise; | 根据指定条件查询数据库中的数据。 |
导入模块
import relationalStore from '@ohos.data.relationalStore'
创建数据库
const config: relationalStore.StoreConfig = {
name: 'user.db', // 数据库文件名称
securityLevel: relationalStore.SecurityLevel.S1, // 数据库安全级别
encrypt: false // 是否加密
}
// 创建数据库
this.database = await relationalStore.getRdbStore(getContext(this), config)
运行sql语句创建表
let sql = 'CREATE TABLE IF NOT EXISTS User (id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL)'
// 创建表
await this.database.executeSql(sql)
定义实体对象
@Observed // 配合ObjectLink使用,当对象数组内属性发生变化时,可以触发渲染
class User {
id: number
name: string
constructor(name: string, id?: number) {
this.id = id
this.name = name
}
}
对数据库进行增删改查操作
let user = {
name: `user${Math.floor(Math.random() * 1000)}`
}
this.database.insert('User', user)
.then((rowId) => {
if (rowId != -1) {
showToast('添加成功')
this.users.push(new User(user.name, rowId))
}
})
.catch((err) => {
console.error(TAG, `添加失败 ${JSON.stringify(err)}`)
})
生成的持久化文件存储在 /data/app/el2/100/database/com.example.storedemo/entry/rdb
中。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。