【鸿蒙HarmonyOS NEXT】用户首选项Preference存储数据

【鸿蒙HarmonyOS NEXT】数据存储之用户首选项Preference

一、环境说明

  1. DevEco Studio 版本:

  2. API版本:以12为主

二、Preference运作机制

应用场景:

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

Preference运作机制

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

三、示例代码加以说明

沿用【鸿蒙HarmonyOS NEXT】页面之间相互传递参数博文中的代码,进行测试。

代码改写如下:

  1. LoginPage完整代码如下:

    typescript 复制代码
    import { router } from '@kit.ArkUI';
    
    // 引入Context相关
    import { common } from '@kit.AbilityKit';
    import { hilog } from '@kit.PerformanceAnalysisKit';
    
    // 引入preferences相关
    import { preferences } from '@kit.ArkData';
    import { util } from '@kit.ArkTS';
    
    // 定义ihlog日志常量相关
    const TAG: string = '[LoginPage_Context]';
    const DOMAIN_NUMBER: number = 0xFF00;
    
    @Preview
    @Entry
    @Component
    struct LoginPage {
      @State message: string = '登录页';
      @State btnMsg: string = '登录';
      @State account: string = ''; // 账号状态变量
      @State password: string = ''; // 密码状态变量
      @State isShowProgress: boolean = false; // 显示进度指示器的状态变量
    
      // 获取Context
      private context = getContext(this) as common.UIAbilityContext;
    
      // 获取首选项对象,其中userInfo可自定义
      private options: preferences.Options = { name: 'userInfo' };
      private dataPreferences: preferences.Preferences = preferences.getPreferencesSync(this.context, this.options);
    
      build() {
        Column() {
          Text(this.message)
            .id('HelloWorld')
            .fontSize(20)
            .fontWeight(FontWeight.Bold)
            .width('100%')
            .height(50)
            .textAlign(TextAlign.Center)
            .backgroundColor(0xF1F3F5)
    
          Image($r('app.media.startIcon'))
            .width(150)
            .height(150)
            .margin({ top: 40, bottom: 40 })
    
          TextInput({ placeholder: '请输入手机号' })
            .maxLength(11)// 最大长度
            .type(InputType.Number)// 输入类型为数字
            .inputStyle()// 应用自定义样式
            .onChange((value: string) => {
              this.account = value; // 更新账号状态
            })
          Line().lineStyle() // 应用自定义Line样式
    
          // 密码输入框
          TextInput({ placeholder: '请输入密码' })
            .maxLength(12)// 最大长度
            .type(InputType.Password)// 输入类型为密码
            .inputStyle()// 应用自定义样式
            .onChange((value: string) => {
              // TODO: 生产环境需要使用正则表达式对手机号进行验证
              this.password = value; // 更新密码状态
            })
          Line().lineStyle() // 应用自定义Line样式
    
    
          Button(this.btnMsg)
            .width('80%')
            .margin({ top: 100 })
            .height(50)
            .onClick(() => {
              if (this.account === undefined || this.account === '') {
                console.info('请输入账号')
                return
              }
    
              if (this.password === undefined || this.password === '') {
                console.info('请输入密码')
                return
              }
    
              // 使用ArkData用户首选项 本地以Key/Value形式存储用户信息数据
              if (this.dataPreferences.hasSync('account')) {
                hilog.info(DOMAIN_NUMBER, TAG, `account: ${this.account}`);
              } else {
                hilog.info(DOMAIN_NUMBER, TAG, `The key 'account' does not contain.`);
                // 此处以此键值对不存在时写入数据为例
                this.dataPreferences.putSync('account', this.account);
                // 当字符串有特殊字符时,需要将字符串转为Uint8Array类型再存储
                let uInt8Password = new util.TextEncoder().encodeInto(this.password);
                this.dataPreferences.putSync('password', uInt8Password);
              }
    
              // 跳转到首页
              router.pushUrl({
                url: 'pages/HomePage',
                params: {
                  account: this.account,
                  password: this.password
                }
              })
            })
        }
        .height('100%')
        .width('100%')
        .padding(0)
      }
    }
    
    // TextInput组件的自定义样式扩展
    @Extend(TextInput)
    function inputStyle() {
      .placeholderColor(Color.Gray) // 占位符颜色
      .height(50) // 输入框高度
      .fontSize(15) // 字体大小
      .backgroundColor(0xF1F3F5) // 背景颜色
      .width('90%') // 宽度为父组件的100%
      .padding({ left: 12 }) // 左侧填充
      .margin({ top: 15 }) // 上方边距
    }
    
    // Line组件的自定义样式扩展
    @Extend(Line)
    function lineStyle() {
      .width('100%') // 宽度为父组件的100%
      .height(1) // 高度
      .backgroundColor(0xF1F3F5) // 背景颜色
    }
  2. HomePage完整代码如下:

    typescript 复制代码
    import { router } from '@kit.ArkUI';
    import { preferences } from '@kit.ArkData';
    import {common} from '@kit.AbilityKit'
    import { util } from '@kit.ArkTS';
    import { hilog } from '@kit.PerformanceAnalysisKit';
    
    // 定义ihlog日志常量相关
    const TAG: string = '[HomePage_Context]';
    const DOMAIN_NUMBER: number = 0xFF01;
    
    @Preview
    @Entry
    @Component
    struct HomePage {
      @State message: string = '首页';
      // 获取前一个页面传递过来的数据
      @State account: string = ''
      @State password: string = ''
    
      // 获取Context
      private context = getContext(this) as common.UIAbilityContext;
    
      // 获取首选项对象
      private options: preferences.Options = { name: 'userInfo' };
      private dataPreferences: preferences.Preferences = preferences.getPreferencesSync(this.context, this.options);
    
      aboutToAppear(): void {
        // 使用ArkData用户首选项 获取用户数据
        this.account = this.dataPreferences.getSync('account', 'default').toString(); // 'default' 可以换成其他的,如null,但这个参数必须给
        hilog.info(DOMAIN_NUMBER, TAG, `account: ${this.account}`);
        // 当获取的值为带有特殊字符的字符串时,需要将获取到的Uint8Array转换为字符串
        let uInt8Array2 : preferences.ValueType = this.dataPreferences.getSync('password', new Uint8Array(0));
        let textDecoder = util.TextDecoder.create('utf-8');
        this.password = textDecoder.decodeToString(uInt8Array2 as Uint8Array);
        hilog.info(DOMAIN_NUMBER, TAG, `password: ${this.password}`);
      }
    
      build() {
        Column() {
          Text(this.message)
            .fontSize(30)
            .width('100%')
            .height(50)
            .textAlign(TextAlign.Center)
            .backgroundColor(0xF1F3F5)
    
          Blank().height(120)
    
          Text(`接收到的用户名:${this.account}`)
            .fontSize(20)
            .width('100%')
            .height(50)
            .padding({ left: 12, right: 12 })
    
          Text(`接收到的密码:${this.password}`)
            .fontSize(20)
            .width('100%')
            .height(50)
            .padding({ left: 12, right: 12 })
    
    
          Button('返回上一页')
            .width('80%')
            .margin({ top: 120 })
            .height(50)
            .onClick(() => {
              // 返回登录页面
              router.showAlertBeforeBackPage({ message: '确认返回上一页吗?' })
              router.back({
                url: 'pages/LoginPage',
                params: {
                  msg: 'homepage'
                }
              })
            })
        }
        .height('100%')
        .width('100%')
      }
    }

测试步骤如下:

  1. 打开模拟器,并将代码部署到模拟器上,当模拟器正常运行代码后,输入用户名和密码
  2. 点击手机模拟器上应用的登录按钮,跳转到了首页,然后再从首页返回登录页,查看控制台日志,内容如截图红色框或者首页文字所示:

四、小结

通过上述的说明和示例演示,相信大家已经很清楚Preferences用户首选项存储数据的用法了。细心的读者朋友可能会问,如何调用flush持久化到文件中以及如何删除文件?另外,在真实的开发过程中Preferences不适合存放过多的数据,也不支持通过配置加密,适用的场景一般为应用保存用户的个性化设置(字体大小,是否开启夜间模式)等。HarmonyOS官网推荐使用键值型数据库持久化此类数据。感兴趣的读者朋友可以尝试下,看看使用键值型数据库持久化此类数据是否可以正常运行呢?欢迎大家的留言,我们在留言区进行讨论。

相关推荐
一码平川SHI2 小时前
鸿蒙_异步详解
华为·harmonyos
郝晨妤2 小时前
鸿蒙【项目打包】- .hap 和 .app;(测试如何安装发的hap包)(应用上架流程)
华为od·华为·harmonyos·鸿蒙
SuperHeroWu72 小时前
【HarmonyOS】深入理解@Observed装饰器和@ObjectLink装饰器:嵌套类对象属性变化
华为·harmonyos·状态管理·observed·objectlink·嵌套对象
lichong9515 小时前
【Harmony】轮播图特效,持续更新中。。。。
android·linux·服务器·harmonyos·鸿蒙·swiper
爱桥代码的程序媛5 小时前
鸿蒙OpenHarmony【轻量系统内核通信机制(消息队列)】子系统开发
单片机·消息队列·内核·harmonyos·鸿蒙·鸿蒙系统·openharmony
今人不见古时月,今月曾经照古人5 小时前
Harmony应用 ArkTs AES 加密方法之GCM对称加密
harmonyos·arkts·鸿蒙应用
OH五星上将12 小时前
OpenHarmony(鸿蒙南向开发)——小型系统内核(LiteOS-A)【Perf调测】
harmonyos·openharmony·鸿蒙开发·liteos-a·鸿蒙内核·子系统·鸿蒙系统开发
Python私教13 小时前
鸿蒙 OS 开发零基础快速入门教程
android·华为·harmonyos