当前位置:   article > 正文

应用数据持久化方式汇总_persistenstorage

persistenstorage

应用数据持久化方式汇总

本文简单介绍了OpenHarmony持久化数据的几种方式

IDE:DevEco Studio 4.0 Release

SDK:3.2.13.5

模型:Stage

PersistenStorage: 持久化存储UI状态

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>获取属性名称列表
使用PersistenStorage
  1. 定义要持久化的属性以及默认值

    PersistentStorage.PersistProp<string>('string', 'haha')
    
    • 1
  2. 使用AppStorage获取属性 或者在组件中使用 @StorageLink

     AppStorage.get('haha')
     @StorageLink('string') str: string = 'hello world'
    
    • 1
    • 2
注意
  • 生成的持久化文件存储在 /data/storage/el2/100/base/xx.xx.xx/haps/xx/files/persistent_storage 中,以xml的格式存储

    img

  • PersistentStorage.PersistProp 需要在 AppStorage访问属性(SetOrCreate,@StorageLInk)之前调用。如果反过来,就会出现上一次持久化的值被属性的默认值给覆盖掉了 。API9下 PersistentStorage只能在UI页面中使用

  • PersistentStorage 允许的类型有:number,string等简单类型,还有可以被 JSON.stringifyJSON.parse重构的对象。不支持嵌套对象,对象数组,undefined和null

  • 观察aboutToAppear 方法的打印,发现应用关闭再打开后bool 和 person 的类型都变为了string。这就需要自己做判断转换类型了。尤其注意boolean类型,一不小心false变成'false',隐式转换成true(4.0已修改)

    img

  • 由于PersistentStorage 是立即同步,所以对于频繁修改的数据不建议使用,且持久化的变量最好小于2kb,否则会拖慢UI响应速度

首选项:@ohos.data.preferences模块

首选项为用户提供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实例有对应的持久化文件,则同时删除其持久化文件。
使用preferences模块
  1. 导入模块

    import dataPreferences from '@ohos.data.preferences'
    
    • 1
  2. 调用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)}`)
      })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
  3. 对数据进行增删改查操作

    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)}`)
        })
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
  4. preferences模块需要调用flush方法,才会进行数据持久化操作

    this.preference.flush()
      .then(() => {
        console.info('flush success')
      })
      .catch(err => {
        console.error(TAG, `flush error: ${JSON.stringify(err)}`)
      })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
注意
  • 生成的持久化文件存储在 /data/storage/el2/100/base/xx.xx.xx/haps/xx/perferences/xxx 中,以xml的格式存储,且类型信息也存储了

    img

  • put方法支持的类型有 number | string | boolean | Array<number> | Array<string> | Array<boolean>

  • preferences 模块是将数据加载到内存中去,所以建议存储数据不超过一万条。否则就应该考虑用数据库来进行存储

键值型数据库:@ohos.data.distributedKVStore模块

键值型数据库存储键值型的数据,支持单版本数据库和设备协同数据库两种。

每个应用程序最多同时打开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[]>获取匹配指定前缀的所有键值对
使用键值型数据库
  1. 导入模块

    import distributedKVStore from '@ohos.data.distributedKVStore';
    
    • 1
  2. 获取KVManager实例,用于管理数据库对象

    // KVManager配置信息
    const config: distributedKVStore.KVManagerConfig = {
      context: getContext(this), // 上下文信息
      bundleName: 'com.example.storedemo' // 所属应用
    }
    // 创建KVManager
    const manager = distributedKVStore.createKVManager(config)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
  3. 获取数据库实例

    // 数据库配置信息
    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)}`)
      })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
  4. 对数据库进行增删改查操作

    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)}`)
        })
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
注意
  • 生成的持久化文件存储在 /data/app/el2/100/database/xx.xx.xx/xx/kvdb/xxx(sortedId)/single_ver/main 中,信息已经做了加密处理。

    如果想要查看数据库文件,需要把这三个文件都拷贝出来放在同一文件夹下,用sqlite客户端工具打开。拷贝命令:hdc file recv srcPath targetPath

    img


    img

  • 除了指定前缀外,getEntries还支持接收一个Query查询条件,更加细化查询条件。键值型数据库也支持开启事务。

关系型数据库

关系型数据库基于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;根据指定条件查询数据库中的数据。
使用关系型数据库:@ohos.data.relationalStore
  1. 导入模块

    import relationalStore from '@ohos.data.relationalStore'
    
    • 1
  2. 创建数据库

    const config: relationalStore.StoreConfig = {
      name: 'user.db', // 数据库文件名称
      securityLevel: relationalStore.SecurityLevel.S1, // 数据库安全级别
      encrypt: false // 是否加密
    }
    // 创建数据库
    this.database = await relationalStore.getRdbStore(getContext(this), config)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
  3. 运行sql语句创建表

    let sql = 'CREATE TABLE IF NOT EXISTS User (id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL)'
    // 创建表
    await this.database.executeSql(sql)
    
    • 1
    • 2
    • 3
  4. 定义实体对象

    @Observed // 配合ObjectLink使用,当对象数组内属性发生变化时,可以触发渲染
    class User {
      id: number
      name: string
    
      constructor(name: string, id?: number) {
        this.id = id
        this.name = name
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
  5. 对数据库进行增删改查操作

    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)}`)
      })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
注意
  • 生成的持久化文件存储在 /data/app/el2/100/database/com.example.storedemo/entry/rdb 中。

    img


    img

声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号