鸿蒙HarmonyOS NEXT开发:数据长期化方案剖析与实践

打印 上一主题 下一主题

主题 803|帖子 803|积分 2409



(一)PersistentStorage 实现应用长期化数据管理

功能概述

        通过 PersistentStorage 类可管理应用长期化数据,能将特定标记的长期化数据链接到 AppStorage 中,再由 AppStorage 接口访问对应数据。长期化后的数据会生本钱地 xml 文件保存,文件路径为 /data/app/el2/100/base/<bundleName>/haps/<hapName>/files/persistent_storage。
特性



  • 自动同步:PersistentStorage 会自动和 AppStorage 中数据同步。
  • 长期化存储:存储的数据为长期化存储。
  • 初始值设置:利用 PersistentStorage.PersistProp (' 属性名 ', 初始值) 设置初始值时,只有第一次会收效。

代码示例及步骤

首先,进行长期化数据的设置
        在以下代码中,我们利用 PersistentStorage.persistProp 来设置长期化数据。这里我们设置了一个名为 'num' 的属性,初始值为 0。这一步是创建长期化数据的关键。
  1. // 持久化模块,设置键值及初始化的值
  2. PersistentStorage.persistProp('num',0)
复制代码
然后,在组件中绑定长期化数据
        在 @Entry 装饰的组件中,我们利用 @StorageLink('num') 来将组件中的 num 属性与之前设置的长期化数据 'num' 进行绑定。这样,组件中的数据变化会反映到长期化存储中。
  1. @Entry
  2. @Component
  3. struct Index {
  4.     // 绑定模块,使用AppStoage的API,如@StorageLink(键)、@StorageProp(键)修饰,使用AppStoage.get、AppStoage.set等方法调用
  5.     @StorageLink('num') num :number = 0
  6.     build() {
  7.         RelativeContainer() {
  8.             Text(this.num.toString())
  9.               .onClick(() => {
  10.                     this.num++
  11.                 })
  12.               .fontSize(50)
  13.               .fontWeight(FontWeight.Bold)
  14.               .alignRules({
  15.                     center: { anchor: '__container__', align: VerticalAlign.Center },
  16.                     middle: { anchor: '__container__', align: HorizontalAlign.Center }
  17.                 })
  18.         }
  19.       .height('100%')
  20.       .width('100%')
  21.     }
  22. }
复制代码
 完整代码:

  1. // 代码示例
  2. PersistentStorage.persistProp('num',0)      // 持久化模块,参数1:键, 参数2:初始化的值
  3. @Entry
  4. @Component
  5. struct Index {
  6.    // 绑定模块 使用AppStoage的API,如@StorageLink(键)、@StorageProp(键)修饰,使用AppStoage.get、AppStoage.set等方法调用
  7.   @StorageLink('num') num :number = 0
  8.   build() {
  9.     RelativeContainer() {
  10.       Text(this.num.toString())
  11.         .onClick(() => {
  12.           this.num++
  13.         })
  14.         .fontSize(50)
  15.         .fontWeight(FontWeight.Bold)
  16.         .alignRules({
  17.           center: { anchor: '__container__', align: VerticalAlign.Center },
  18.           middle: { anchor: '__container__', align: HorizontalAlign.Center }
  19.         })
  20.     }
  21.     .height('100%')
  22.     .width('100%')
  23.   }
  24. }
复制代码
(二)用户首选项长期化


功能概述

为应用提供 Key-Value 键值型的数据处置惩罚能力,支持应用长期化轻量级数据,并可对其进行修改和查询。

操作步骤



  • 创建实例:需先创建用户首选项长期化实例存放到磁盘目录中,通过 preferences.getPreferencesSync (getContext (),{name:'xxx'}) 来创建,其中参数 1 为"上下文",参数 2 为与 Preferences 实例相关的配置选项,name 为必填参数,指 Preferences 实例的名称。
  • 修改数据:利用实例对象中的 putSync (key, 数据) 方法实现数据修改,有则改、无则加。
  • 获取数据:通过 getSync (key, 默认值) 方法可获取对应的值,当 key 不存在时,则得到的值为默认值。
  • 删除数据:调用 deleteSync (key) 方法可实现删除该键的数据。
  • 刷盘同步:对实例进行操作后需要调用 flush () 方法进行刷盘,才会同步到当地磁盘。
封装工具类完整代码:

  1. // 封装用户首选项持久化的工具类
  2. import { preferences } from "@kit.ArkData";
  3. export class preferencesUtil<T extends preferences.ValueType>{
  4.     private pre: preferences.Preferences
  5.     // 构造函数进行初始化,传name参数
  6.     constructor(name: string) {
  7.         this.pre = preferences.getPreferencesSync(getContext(),{name:name})
  8.     }
  9.     // 增、改 键-值
  10.     put(key:string, value:T):T{
  11.         this.pre.putSync(key,value)
  12.         this.pre.flush()
  13.         return value
  14.     }
  15.     // 查  键-默认值(查不到返回的为默认值)
  16.     get(key:string, value:T):T{
  17.         return this.pre.getSync(key,value) as T
  18.     }
  19.     // 删  键
  20.     del(key:string){
  21.         this.pre.deleteSync(key)
  22.         this.pre.flush()
  23.     }
  24. }
复制代码
测试代码示例

  1. // 测试代码
  2. import { preferencesUtil } from '../preferencesUtil'
  3. @Entry
  4. @Component
  5. struct Index {
  6.     // 实例化用户首选项工具
  7.     pre = new preferencesUtil<number>('xxx')
  8.     // 获取首次数据
  9.     @State num :number = this.pre.get('xxx',0)
  10.     build() {
  11.         Column() {
  12.             Text(this.num.toString())
  13.             Button('加一')
  14.                .onClick(()=>{
  15.                     // 更新数据
  16.                     this.num = this.pre.put('xxx', ++this.num)
  17.                 })
  18.         }
  19.        .height('100%')
  20.        .width('100%')
  21.     }
  22. }
复制代码

(三)数据库长期化(基于关系型数据库)

功能概述

        关系型数据库(Relational Database,RDB)基于 SQLite 组件提供了一套完整的对当地数据库进行管理的机制,对外提供一系列增、删、改、查等接口,也可直接运行用户输入的 SQL 语句来满足复杂场景需要。
官方网址

官方链接
封装工具类及测试代码示例

  1. import { relationalStore, ValuesBucket } from "@kit.ArkData";
  2. // 定义数据的结构
  3. export interface IRdb extends ValuesBucket{
  4.   id:number
  5.   title:string
  6.   content:string
  7. }
  8. export class RDBUtil{
  9.   private tableName = 'rdbName'
  10.   store: relationalStore.RdbStore | undefined = undefined;
  11.   // 初始化
  12.   async init(){
  13.     const store = await relationalStore.getRdbStore(getContext(), {
  14.       // 数据库的名
  15.       name: 'databaseName.db',
  16.       // 安全级别
  17.       securityLevel: relationalStore.SecurityLevel.S1
  18.     })
  19.     // 定义数据库的表
  20.     store.executeSql(`
  21.         CREATE TABLE IF NOT EXISTS ${this.tableName} (
  22.           id INTEGER PRIMARY KEY AUTOINCREMENT,
  23.           title TEXT NOT NULL,
  24.           content TEXT NOT NULL
  25.         )
  26.       `)
  27.     this.store = store
  28.   }
  29.   // 增
  30.   async addSql(title:string, content:string){
  31.     this.store?.executeSql(
  32.       `
  33.       INSERT INTO ${this.tableName} (id, title, content)
  34.       VALUES (null, '${title}', '${content}')
  35.       `
  36.     )
  37.   }
  38.   // 删
  39.   async delSqlById(id:number){
  40.     this.store?.executeSql(`
  41.     DELETE FROM ${this.tableName} WHERE id = ${id};
  42.     `)
  43.   }
  44.   // 改
  45.   async updateSql(id:number, title:string, content:string){
  46.     this.store?.executeSql(`
  47.     UPDATE ${this.tableName}
  48.     SET title = '${title}', content = '${content}'
  49.     WHERE id = ${id}
  50.     `)
  51.   }
  52.   // 查
  53.   async getSql(){
  54.     let dataIndex = this.store?.querySqlSync(`
  55.     SELECT * FROM ${this.tableName}
  56.     `)
  57.     let list:IRdb[] = []
  58.     while (dataIndex?.goToNextRow()){
  59.       list.push(dataIndex.getRow() as IRdb)
  60.     }
  61.     dataIndex?.close()
  62.     return list
  63.   }
  64. }
复制代码
  1. // 测试代码
  2. import { IRdb, RDBUtil } from '../utils/RDBUtil'
  3. @Entry
  4. @Component
  5. struct Index {
  6.   @State list:IRdb[] = []
  7.   rdb = new RDBUtil()
  8.   aboutToAppear(): void {
  9.     this.rdb.init()
  10.   }
  11.   build() {
  12.     Column() {
  13.       Text(JSON.stringify(this.list,null,2))
  14.       Button('加')
  15.         .onClick(()=>{
  16.           this.rdb.addSql('xx','yyy')
  17.         })
  18.       Button('删')
  19.         .onClick(async ()=>{
  20.           await this.rdb.delSqlById(5)
  21.         })
  22.       Button('改')
  23.         .onClick(()=>{
  24.           this.rdb.updateSql(1,'jjj','ttt')
  25.         })
  26.       Button('查')
  27.         .onClick(async () => {
  28.           this.list = await this.rdb.getSql()
  29.         })
  30.     }
  31.     .height('100%')
  32.     .width('100%')
  33.   }
  34. }
复制代码

留意事项

利用 SQL 语句存在一个 bug,即增、删、改之后不能立刻查到处置惩罚后的结果。解决方法可以是延迟查询大概查询官网看是否有不利用 SQL 语句的替代方式。比方以下代码情况:
  1. // 如 一下代码,不能立刻得到处理后的结果,处理方法延迟或查询官网不使用SQL语句
  2. Button('加')
  3.   .onClick(async ()=>{
  4.     this.rdb.addSql('xx','yyy')
  5.     this.list = await this.rdb.getSql()
  6.   })
  7. Button('删')
  8.   .onClick(async ()=>{
  9.     await this.rdb.delSqlById(5)
  10.     this.list = await this.rdb.getSql()
  11.   })
  12. Button('改')
  13.   .onClick(async ()=>{
  14.     this.rdb.updateSql(1,'jjj','ttt')
  15.     this.list = await this.rdb.getSql()
  16.   })
复制代码





免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

悠扬随风

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表