HarmonyOS 应用开发之通过用户首选项实现数据持久化

news/2024/7/21 9:33:28 标签: harmonyos, 华为, 程序员, 鸿蒙开发, 移动开发

应用数据持久化概述

应用数据持久化,是指应用将内存中的数据通过文件或数据库的形式保存到设备上。内存中的数据形态通常是任意的数据结构或数据对象,存储介质上的数据形态可能是文本、数据库、二进制文件等。

OpenHarmony标准系统支持典型的存储数据形态,包括用户首选项、键值型数据库、关系型数据库。

开发者可以根据如下功能介绍,选择合适的数据形态以满足自己应用数据的持久化需要。

  • 用户首选项(Preferences):通常用于保存应用的配置信息。数据通过文本的形式保存在设备中,应用使用过程中会将文本中的数据全量加载到内存中,所以访问速度快、效率高,但不适合需要存储大量数据的场景。

  • 键值型数据库(KV-Store):一种非关系型数据库,其数据以“键值”对的形式进行组织、索引和存储,其中“键”作为唯一标识符。适合很少数据关系和业务关系的业务数据存储,同时因其在分布式场景中降低了解决数据库版本兼容问题的复杂度,和数据同步过程中冲突解决的复杂度而被广泛使用。相比于关系型数据库,更容易做到跨设备跨版本兼容。

  • 关系型数据库(RelationalStore):一种关系型数据库,以行和列的形式存储数据,广泛用于应用中的关系型数据的处理,包括一系列的增、删、改、查等接口,开发者也可以运行自己定义的SQL语句来满足复杂业务场景的需要。

通过用户首选项实现数据持久化

场景介绍

用户首选项为应用提供Key-Value键值型的数据处理能力,支持应用持久化轻量级数据,并对其修改和查询。当用户希望有一个全局唯一存储的地方,可以采用用户首选项来进行存储。Preferences会将该数据缓存在内存中,当用户读取的时候,能够快速从内存中获取数据,当需要持久化时可以使用flush接口将内存中的数据写入持久化文件中。Preferences会随着存放的数据量越多而导致应用占用的内存越大,因此,Preferences不适合存放过多的数据,适用的场景一般为应用保存用户的个性化设置(字体大小,是否开启夜间模式)等。

运作机制

如图所示,用户程序通过ArkTS接口调用用户首选项读写对应的数据文件。开发者可以将用户首选项持久化文件的内容加载到Preferences实例,每个文件唯一对应到一个Preferences实例,系统会通过静态容器将该实例存储在内存中,直到主动从内存中移除该实例或者删除该文件。

应用首选项的持久化文件保存在应用沙箱内部,可以通过context获取其路径。

图1 用户首选项运作机制

约束限制

  • Key键为string类型,要求非空且长度不超过80个字节。

  • 如果Value值为string类型,请使用UTF-8编码格式,可以为空,不为空时长度不超过8192个字节。

  • 内存会随着存储数据量的增大而增大,所以存储的数据量应该是轻量级的,建议存储的数据不超过一万条,否则会在内存方面产生较大的开销。

接口说明

以下是用户首选项持久化功能的相关接口,更多接口及使用方式请见用户首选项。

接口名称描述
getPreferencesSync(context: Context, options: Options): Preferences获取Preferences实例。该接口存在异步接口。
putSync(key: string, value: ValueType): void将数据写入Preferences实例,可通过flush将Preferences实例持久化。该接口存在异步接口。
hasSync(key: string): void检查Preferences实例是否包含名为给定Key的存储键值对。给定的Key值不能为空。该接口存在异步接口。
getSync(key: string, defValue: ValueType): void获取键对应的值,如果值为null或者非默认值类型,返回默认数据defValue。该接口存在异步接口。
deleteSync(key: string): void从Preferences实例中删除名为给定Key的存储键值对。该接口存在异步接口。
flush(callback: AsyncCallback<void>): void将当前Preferences实例的数据异步存储到用户首选项持久化文件中。
on(type: ‘change’, callback: Callback<string>): void订阅数据变更,订阅的数据发生变更后,在执行flush方法后,触发callback回调。
off(type: ‘change’, callback?: Callback<string>): void取消订阅数据变更。
deletePreferences(context: Context, options: Options, callback: AsyncCallback<void>): void从内存中移除指定的Preferences实例。若Preferences实例有对应的持久化文件,则同时删除其持久化文件。

开发步骤

  1. 导入@ohos.data.preferences模块。

    import dataPreferences from '@ohos.data.preferences';
    
  2. 获取Preferences实例。

    Stage模型示例:

    import UIAbility from '@ohos.app.ability.UIAbility';
    import { BusinessError } from '@ohos.base';
    import window from '@ohos.window';
    
    let preferences: dataPreferences.Preferences | null = null;
    
    class EntryAbility extends UIAbility {
      onWindowStageCreate(windowStage: window.WindowStage) {
        let options: dataPreferences.Options = { name: 'myStore' };
        preferences = dataPreferences.getPreferencesSync(this.context, options);
      }
    }
    

    FA模型示例:

    // 获取context
    import featureAbility from '@ohos.ability.featureAbility';
    import { BusinessError } from '@ohos.base';
    
    let context = featureAbility.getContext();
    let options: dataPreferences.Options =  { name: 'myStore' };
    let preferences: dataPreferences.Preferences = dataPreferences.getPreferencesSync(context, options);
    
  3. 写入数据。

    使用putSync()方法保存数据到缓存的Preferences实例中。在写入数据后,如有需要,可使用flush()方法将Preferences实例的数据存储到持久化文件。

    说明:

    当对应的键已经存在时,putSync()方法会修改其值。可以使用hasSync()方法检查是否存在对应键值对。

    示例代码如下所示:

    import util from '@ohos.util';
    if (preferences.hasSync('startup')) {
      console.info("The key 'startup' is contained.");
    } else {
      console.info("The key 'startup' does not contain.");
      // 此处以此键值对不存在时写入数据为例
      preferences.putSync('startup', 'auto');
      // 当字符串有特殊字符时,需要将字符串转为Uint8Array类型再存储
      let uInt8Array = new util.TextEncoder().encodeInto("~!@#¥%……&*()——+?");
      preferences.putSync('uInt8', uInt8Array);
    }
    
  4. 读取数据。

    使用getSync()方法获取数据,即指定键对应的值。如果值为null或者非默认值类型,则返回默认数据。

    示例代码如下所示:

    import util from '@ohos.util';
    let val = preferences.getSync('startup', 'default');
    console.info("The 'startup' value is " + val);
    // 当获取的值为带有特殊字符的字符串时,需要将获取到的Uint8Array转换为字符串
    let uInt8Array : dataPreferences.ValueType = preferences.getSync('uInt8', new Uint8Array(0));
    let textDecoder = util.TextDecoder.create('utf-8');
    val = textDecoder.decodeWithStream(uInt8Array as Uint8Array);
    console.info("The 'uInt8' value is " + val);
    
  5. 删除数据。

    使用deleteSync()方法删除指定键值对,示例代码如下所示:

    preferences.deleteSync('startup');
    
  6. 数据持久化。

    应用存入数据到Preferences实例后,可以使用flush()方法实现数据持久化。示例代码如下所示:

    preferences.flush((err: BusinessError) => {
      if (err) {
        console.error(`Failed to flush. Code:${err.code}, message:${err.message}`);
        return;
      }
      console.info('Succeeded in flushing.');
    })
    
  7. 订阅数据变更。

    应用订阅数据变更需要指定observer作为回调方法。订阅的Key值发生变更后,当执行flush()方法时,observer被触发回调。示例代码如下所示:

    let observer = (key: string) => {
      console.info('The key' + key + 'changed.');
    }
    preferences.on('change', observer);
    // 数据产生变更,由'auto'变为'manual'
    preferences.put('startup', 'manual', (err: BusinessError) => {
      if (err) {
        console.error(`Failed to put the value of 'startup'. Code:${err.code},message:${err.message}`);
        return;
      }
      console.info("Succeeded in putting the value of 'startup'.");
      if (preferences !== null) {
        preferences.flush((err: BusinessError) => {
          if (err) {
            console.error(`Failed to flush. Code:${err.code}, message:${err.message}`);
            return;
          }
          console.info('Succeeded in flushing.');
        })
      }
    })
    
  8. 删除指定文件。

    使用deletePreferences()方法从内存中移除指定文件对应的Preferences实例,包括内存中的数据。若该Preference存在对应的持久化文件,则同时删除该持久化文件,包括指定文件及其备份文件、损坏文件。

    说明:

    • 调用该接口后,应用不允许再使用该Preferences实例进行数据操作,否则会出现数据一致性问题。

    • 成功删除后,数据及文件将不可恢复。

    示例代码如下所示:

    let options: dataPreferences.Options = { name: 'myStore' };
      dataPreferences.deletePreferences(this.context, options, (err: BusinessError) => {
        if (err) {
          console.error(`Failed to delete preferences. Code:${err.code}, message:${err.message}`);
            return;
        }
        console.info('Succeeded in deleting preferences.');
    })
    

为了能让大家更好的学习鸿蒙(HarmonyOS NEXT)开发技术,这边特意整理了《鸿蒙开发学习手册》(共计890页),希望对大家有所帮助:https://qr21.cn/FV7h05

鸿蒙开发学习手册》:

如何快速入门:https://qr21.cn/FV7h05

  1. 基本概念
  2. 构建第一个ArkTS应用
  3. ……

开发基础知识:https://qr21.cn/FV7h05

  1. 应用基础知识
  2. 配置文件
  3. 应用数据管理
  4. 应用安全管理
  5. 应用隐私保护
  6. 三方应用调用管控机制
  7. 资源分类与访问
  8. 学习ArkTS语言
  9. ……

基于ArkTS 开发:https://qr21.cn/FV7h05

  1. Ability开发
  2. UI开发
  3. 公共事件与通知
  4. 窗口管理
  5. 媒体
  6. 安全
  7. 网络与链接
  8. 电话服务
  9. 数据管理
  10. 后台任务(Background Task)管理
  11. 设备管理
  12. 设备使用信息统计
  13. DFX
  14. 国际化开发
  15. 折叠屏系列
  16. ……

鸿蒙开发面试真题(含参考答案):https://qr18.cn/F781PH

鸿蒙开发面试大盘集篇(共计319页):https://qr18.cn/F781PH

1.项目开发必备面试题
2.性能优化方向
3.架构方向
4.
鸿蒙开发系统底层方向
5.鸿蒙音视频开发方向
6.鸿蒙车载开发方向
7.鸿蒙南向开发方向


http://www.niftyadmin.cn/n/5465794.html

相关文章

vs2022断点找bug出错(打上100个断点)

初步分析&#xff1a;故障出自-具体功能模块 进一步分析&#xff1a;故障出自-该功能代码流程 进一步分析&#xff1a;从该功能起点-终点&#xff0c;一路打100个断点

Zookeeper中的脑裂

简单点来说&#xff0c;脑裂(Split-Brain) 就是比如当你的 cluster 里面有两个节点&#xff0c;它们都知道在这个cluster 里需要选举出一个 master。那么当它们两个之间的通信完全没有问题的时候&#xff0c;就会达成共识&#xff0c;选出其中一个作为 master。但是如果它们之间…

Mini-React

jsx jsx 是React中对于JavaScript的语法扩展&#xff0c;允许在JavaScript中去写类似于HTML的代码。使得开发者能够以一种更直观和声明式的方式去编写用户界面 vdom vdom是React为了提高性能而去引入的一个虚拟的dom表示。 它是一个轻量级的 JavaScript 对象&#xff0c;用于…

怎么在UE游戏中加入原生振动效果

我是做振动触感的。人类的五感“视听嗅味触”&#xff0c;其中的“触”就是触觉&#xff0c;是指皮肤、毛发与物体接触时的感觉。触感可以带来更加逼真的沉浸式体验。但也许过于司空见惯&#xff0c;也是习以为常&#xff0c;很多人漠视了触感的价值。大家对触感的认知还远远不…

HarmonyOS 应用开发之@Concurrent装饰器:声明并校验并发函数

在使用 TaskPool 时&#xff0c;执行的并发函数需要使用该装饰器修饰&#xff0c;否则无法通过相关校验。 说明&#xff1a; 从API version 9开始&#xff0c;该装饰器支持在ArkTS卡片中使用。 装饰器说明 Concurrent并发装饰器说明装饰器参数无。使用场景仅支持在Stage模型的…

Linux:基本指令篇

文章目录 前言1.ls 指令2.pwd命令3.cd 指令4.touch指令5.mkdir指令&#xff08;重要&#xff09;6.rmdir指令 && rm 指令&#xff08;重要&#xff09;7.man指令&#xff08;重要&#xff09;8.cp指令&#xff08;重要&#xff09;9.mv指令&#xff08;重要&#xff09…

ecology9.0通过自定义按钮给明细表某字段赋值

功能&#xff1a;把主表字段赋值给明细表字段 核心代码&#xff1a; <script>jQuery(document).ready(function(){$(#setcgy).click(function(){var cgy_txt WfForm.getBrowserShowName("field1207");debuggervar cgy WfForm.getFieldValue("field1207…

element-ui avatar 组件源码分享

今日简单分享 avatar 组件的源码实现&#xff0c;主要从以下四个方面&#xff1a; 1、avatar 组件页面结构 2、avatar 组件属性 3、avatar 组件事件 4、avatar 组件 slot 一、avatar 组件页面结构 二、avatar 组件属性 2.1 icon 属性&#xff0c;设置头像的图标类型&…