HarmonyOS应用数据持久化-KV数据库存储用户数据
简介
本示例使用@ohos.data.distributedKVStore (分布式键值数据库)接口,持久化存储用户数据。杀死进程后重新进入app,展示退出前用户数据信息。
开发思路
-
参考官方KV数据库文档进行学习,发现学习路径与首选项持久化数据库雷同。都需要创建一个数据库文件,在该文件中根据标记存储数据(键值对)
-
设计一个KV数据库操作工具类,封装初始化kv数据库的实例对象
(kvStore),使用这个对象进行增上改查。 -
数据库的名字
(kvStoreId),要存储用户时的键名(userInfoKey),抽取到通用自定义常量文件中,方便复用和扩展。 -
在入口类中初始化项目,注意,注意,注意:
经测试,要在
onWindowStageCreate中初始化。在onCreate中有问题。经分析,应该是生命周期问题,但是参考官方文档后,又无法与文档相悖。无法总结其原理,只好记录于此。记下来,初始化位置选onWindowStageCreate -
在UI中使用较为简单,业务处调用工具类存储数据,
aboutToAppear调用工具类获取数据。
代码编写
src/main/ets/common/DxConstants.ets
export default class DxConstants{
// kv数据库的名字
static readonly kvStoreId : string= "Dxin"
//kv数据库中存储 用户数据的键名
static readonly userInfoKey : string= "userinfo"
}
src/main/ets/common/DxKvStoreUtil.ets
import { Context } from '@kit.AbilityKit';
import { distributedKVStore } from '@kit.ArkData';
import { BusinessError } from '@kit.BasicServicesKit';
class DxKvStoreUtil {
/*
* KV数据库可以设计成 map 用不同的kv存储不同的数据 注意每个应用同时打开KV数据库 数量最多 16 个
* 此处 为demo案例,未设计为 map。如果设计为map的用法,参考如下网址的首选项工具类
* https://juejin.cn/post/7451824088924553231
* */
kvStore: distributedKVStore.SingleKVStore | undefined = undefined;
// 1. 初始化 kvstore
async kvStoreInit(kvStoreName: string, context: Context) {
let kvManger: distributedKVStore.KVManager | undefined = undefined
const kvMangerConfig: distributedKVStore.KVManagerConfig = {
context,
bundleName: getContext(context).applicationInfo.name
}
kvManger = distributedKVStore.createKVManager(kvMangerConfig)
const options: distributedKVStore.Options = {
createIfMissing: true,
encrypt: false,
backup: false,
autoSync: false,
// kvStoreType不填时,默认创建多设备协同数据库
kvStoreType: distributedKVStore.KVStoreType.SINGLE_VERSION,
// 多设备协同数据库:kvStoreType: distributedKVStore.KVStoreType.DEVICE_COLLABORATION,
securityLevel: distributedKVStore.SecurityLevel.S1
};
// --------------------**** 测试代码 start-------------------
// 获取应用所有创建过的 kvStore 需要根据 BundleName
// 此处测试代码对本示例功能无影响,纯粹想测一下 getAllKVStoreId(appid) 这个API
// let appid = getContext(context).applicationInfo.name
// let stroeIdArr: string [] = await kvManger.getAllKVStoreId(appid)
// if (stroeIdArr.includes(kvStoreName)) {
// // 已经存在
// console.log("dxin => ", appid, `里已经存在${kvStoreName} kv实例`)
// } else {
// console.log("dxin => ", appid, `里还没有@@存在${kvStoreName} kv实例`)
// }
// --------------------**** 测试代码 end-------------------
let store = await kvManger.getKVStore<distributedKVStore.SingleKVStore>(kvStoreName, options)
if (store !== undefined) {
this.kvStore = store
console.info(`Dxin => 获取名字叫${kvStoreName}的 KVStore 成功.`);
} else {
console.info(`Dxin => 获取名字叫${kvStoreName}的 KVStore 失败@@.`);
}
}
// 2.put 方法,注意put的数据有类型要求
async putData(keyName: string, valueData: Uint8Array | string | number | boolean) {
try {
if (this.kvStore != undefined) {
this.kvStore.put(keyName, valueData)
.then(() => {
console.info(`Dxin => 向${keyName} 去 put 时成功了`);
})
.catch((err: BusinessError) => {
console.error(`Dxin => 向 ${keyName} 去 put 时失败了. Code:${err.code},message:${err.message}`);
})
}
} catch (e) {
let error = e as BusinessError;
console.error(`Dxin => 向${keyName} 去 put 时发生了未知错误. Code:${error.code},message:${error.message}`);
}
}
//3. 使用 kvStore 获取具体的数据
async getData(keyName: string) {
if (this.kvStore === undefined) {
console.error(`Dxin => 从${keyName} 去 get 时发现,这个kv数据库都不存在`);
return
}
let data = await this.kvStore.get(keyName)
console.log(`Dxin => 从${keyName}成功获取数据. Data:${data}`)
return data
}
//4. 删除 指定键名对应的数据
deleteData(keyName: string) {
if (this.kvStore === undefined) {
console.error(`Dxin => 从${keyName} 去 删除数据 时发现,kv数据库都不存在`);
return
}
this.kvStore.delete(keyName)
.then(() => {
console.info('Dxin => 成功地从${keyName}中删除数据');
})
.catch((err: BusinessError) => {
console.error(`Dxin => 失败地从${keyName}中删除数据. Code:${err.code},message:${err.message}`);
})
}
}
export default new DxKvStoreUtil()
src/main/ets/kvstoreability/KvStoreAbility.ets
async onWindowStageCreate(windowStage: window.WindowStage) {
// 此处调用方法一定记得 await 等待初始化kv数据库成功再去显示UI 如果异步显示UI 会导致KV 还未初始化完呢
// 经过测试,该方法放在 onWindowStageCreate 可行
// 经过测试,该方法放在 onCreate 不可行 执行时机不同,生命周期只是先后顺序,并非onCreate结束后再onWindowStageCreate
await DxKvStoreUtil.kvStoreInit(DxConstants.kvStoreId, this.context)
console.log("Dxin => 入口类初始化了KV数据库:", DxConstants.kvStoreId)
windowStage.loadContent('pages/Index', (err) => {
if (err.code) {
return;
}
});
}
src/main/ets/pages/Index.ets
import DxConstants from '../common/DxConstants';
import DxKvStoreUtil from '../common/DxKvStoreUtil';
// 用户模型
class Userinfo {
username: string
password: string
constructor(username: string, password: string) {
this.username = username
this.password = password
}
}
@Entry
@Component
struct Index {
@State userinfo: Userinfo = new Userinfo("dxin", "123")
async aboutToAppear(): Promise<void> {
// KV数据库获取
let userinfoStr: string = await DxKvStoreUtil.getData(DxConstants.userInfoKey) as string
if (userinfoStr === undefined) {
this.userinfo = new Userinfo("dd","666")
}else {
let currentUserinfo = JSON.parse(userinfoStr) as Userinfo
this.userinfo = currentUserinfo
}
}
build() {
Column({ space: 30 }) {
Text(`欢迎${this.userinfo.username},你的密码是${this.userinfo.password}`)
TextInput({ placeholder: "用户名", text:$$this.userinfo.username })
.onFocus(() => {
this.userinfo.username = ""
})
TextInput({ placeholder: "密码", text: $$this.userinfo.password })
.onFocus(() => {
this.userinfo.password = ""
})
Button("KV数据库应用")
.onClick(() => {
// KV数据库存储 注意存储的数据类型不能是对象,只能是 Uint8Array | string | number | boolean
let userinfoStr = JSON.stringify(this.userinfo)
DxKvStoreUtil.putData(DxConstants.userInfoKey, userinfoStr)
})
}
.width('100%')
.height('100%')
}
}