【鸿蒙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官网推荐使用键值型数据库持久化此类数据。感兴趣的读者朋友可以尝试下,看看使用键值型数据库持久化此类数据是否可以正常运行呢?欢迎大家的留言,我们在留言区进行讨论。

相关推荐
Random_index7 小时前
#Uniapp篇:支持纯血鸿蒙&发布&适配&UIUI
uni-app·harmonyos
鸿蒙自习室11 小时前
鸿蒙多线程开发——线程间数据通信对象02
ui·harmonyos·鸿蒙
SuperHeroWu713 小时前
【HarmonyOS】鸿蒙应用接入微博分享
华为·harmonyos·鸿蒙·微博·微博分享·微博sdk集成·sdk集成
zhangjr057516 小时前
【HarmonyOS Next】鸿蒙实用装饰器一览(一)
前端·harmonyos·arkts
诗歌难吟4641 天前
初识ArkUI
harmonyos
SameX1 天前
HarmonyOS Next 设备安全特性深度剖析学习
harmonyos
郭梧悠1 天前
HarmonyOS(57) UI性能优化
ui·性能优化·harmonyos
郝晨妤1 天前
鸿蒙原生应用开发元服务 元服务是什么?和App的关系?(保姆级步骤)
android·ios·华为od·华为·华为云·harmonyos·鸿蒙
Peace*1 天前
HarmonyOs鸿蒙开发实战(16)=>沉浸式效果第一种方案一窗口全屏布局方案
harmonyos·鸿蒙·鸿蒙系统
howard20052 天前
鸿蒙实战:页面跳转传参
harmonyos·跳转·router·传参