HarmonyOS Next开发,使用Promise异步回调方式封装用户首选项(preferences)

目录

前言

版本说明:本文的API版本为12

一、业务场景

场景1(APP欢迎页):

 场景2(搜索功能):

场景3(存储token):

二、封装用户首选项API

1、创建首选项工具类(PreferencesUtil)

2、获取首选项实例

3、销毁首选项实例

4、从首选项实例中获取键对应的值

5、从首选项实例中写入数据

 6、new一下工具类,并导出

 三、完整文件代码

四、使用首选项工具类

附录


前言

        本专栏记录鸿蒙应用开发的一些知识,供鸿蒙开发者学习。笔者目前还是个小菜鸡,鸿蒙开发也是我看相关资料自学的,所以本文有些地方可能考虑不够周到,有些纰漏,就当抛砖引玉,还望读者海涵。目前HarmonyOS Next已经发布,API已更新至12,只有鸿蒙的开发者越来越多,才能更好的去改进HarmonyOS,去做好我们国人自己的系统,防止被别人卡脖子。本专栏适合初学者做一个入门,同时默认读者具备一定前端基础。本专栏的内容可以做一些课设,毕设之类的。但对于企业中的真实需求,可能考虑不够周到。因为笔者目前还没有工作(T_T)


         本文主要讲解用户首选项的封装。在鸿蒙应用开发中,用户首选项为应用提供Key-Value键值型的数据处理能力,支持应用持久化轻量级数据,并对其修改和查询。简单来说,就是可以存储数字类型、布尔类型、字符串类型及其对应的数组。Key要求非空,长度不超过80字节;Value的大小不超过8192字节。官方文档地址:用户首选项Preferences


版本说明:本文的API版本为12


一、业务场景

场景1(APP欢迎页):

        比如APP欢迎页,用户需要同意隐私政策,才可以继续访问APP(如下图)。Key-Value 键值型存储恰好满足这一业务需求。我们只需在用户点击同意时,用K-V保存用户这个操作行为,等下一次用户再点开APP,只需查看这个Key中是否有值,再判断用户是否可以访问APP即可。

 场景2(搜索功能):

        在搜索功能中,我们一般需要保存用户的搜索记录,并在页面中显示用户的最近搜索内容。而用户搜索记录,一般是字符串的形式,若干个搜索记录就是一个字符串数组。而用户首选项恰好可以存储字符串数组。

        

场景3(存储token):

        了解前后端分离开发的读者应该知道,token常用于用户的身份校验。当用户登录成功后,后端服务器会返回token,而前端在访问后端某些资源时,必须携带token用于校验身份。而token的存储,也可以用到用户首选项。


二、封装用户首选项API

        在项目中,为了代码的可维护性和可读性,不建议单独使用首选项。一般需封装成一个工具类,在需要时,调用工具类里的方法。

1、创建首选项工具类(PreferencesUtil)

import { preferences } from '@kit.ArkData'

class PreferenceUtil{

  // 首选项实例
  private pref: preferences.Preferences | null = null

}

2、获取首选项实例

        根据官方文档,想要获取首选项实例【getPreferences方法】,需要用到context上下文。而在官方文档中,这个context上下文,可以在EntryAbility的生命周期函数中,直接获取。

        所以我们这里把context上下文提出去,在EntryAbility的生命周期函数中,调用我们的初始化首选项方法。在方法里我们可以加点try-catch,提升代码的健壮性。

        *注:函数中的【CommonConstants.G_STORE】是一个字符串常量,是首选项的实例名称,CommonConstants类下存放着各种常量。在项目中,如果在多个地方使用同一个常量,推荐将他封装到常量类里面,这样代码的维护性会更好。

  /*
    * 初始化preferences实例
    * @context  应用上下文
   */
  async loadPreference(context: Context){
    try {
      this.pref = await preferences.getPreferences(context, CommonConstants.G_STORE)
      console.log(`preferences[${CommonConstants.G_STORE}]初始化成功`)
    } catch (err) {
      console.error(`preferences[${CommonConstants.G_STORE}]初始化失败`)
      console.error('err: ', JSON.stringify(err))
    }
  }

3、销毁首选项实例

        同样的,销毁首选项实例需要context上下文。我们这里也将context上下文提出去,在需要的地方,再调用销毁方法。

/*
    * 销毁preferences实例 - 缓存、持久化文件一并销毁
    * @context  应用上下文
   */
  async delPreference(context: Context){
    try {
      await preferences.deletePreferences(context, CommonConstants.G_STORE)
      console.log(`preferences[${CommonConstants.G_STORE}]销毁成功`)
    } catch (err) {
      console.error(`preferences[${CommonConstants.G_STORE}]销毁失败`)
      console.error('err: ', JSON.stringify(err))
    }
  }

4、从首选项实例中获取键对应的值

        想要获取首选项实例中,键对应的值,我们需要用到【get】方法,该方法由首选项实例调用。所以在取值时,我们需要先判断首选项是否初始化成功,即在EntryAbility的生命周期函数中,是否成功调用上文第2小点的【loadPreference】方法。

        调用首选项实例的【get】方法,根据官方文档,我们需要传入key--键,defaultValue--取值失败时,返回的值。我们将这两个参数提出去,由外部调用时提供。

  /*
    * 从preferences实例中获取键对应的值
    * @key            健
    * @defaultValue   获取失败时,返回的值
   */
  async getPreferenceValue(key: string, defaultValue: preferences.ValueType): Promise<preferences.ValueType>{

    let value: preferences.ValueType = defaultValue

    // 获取对应的值之前,先判断preferences是否初始化完成
    if (!this.pref) {
      console.error(`preferences[${CommonConstants.G_STORE}]尚未初始化!`)
      return value
    }

    try {
      value = await this.pref.get(key, defaultValue)
      console.log(`读取preferences[${key} = ${value}]成功`)
    } catch (err) {
      console.error(`读取preferences[${key}]失败 `, JSON.stringify(err))
    }

    return value
  }

5、从首选项实例中写入数据

        从首选项实例写入数据之前,我们同样需要判断首选项是否初始化成功。

        【put】方法仅仅是把key-value值写入内存中,并不做数据的持久化。也就是说,用户一旦退出APP,数据就没有了。而好处就是,响应时间快,因为是保存在内存里。

        【flush】方法则会将首选项实例持久化存储,用户即使退出APP,数据仍然存在。而坏处就是,由于持久化存储是存在磁盘里面,读取数据时,不可避免会有IO操作,数据响应较慢。

        是否使用【flush】方法,根据业务需要而定。这里使用【flush】方法。

/*
  * 从Preferences实例中写入数据
  * @key        健
  * @value      值
 */
  async putPreferenceValue(key: string, value: preferences.ValueType){

    // 写入数据之前,先判断preferences是否初始化完成
    if (!this.pref) {
      console.error(`preferences[${CommonConstants.G_STORE}]尚未初始化!`)
      return
    }

    try {
      await this.pref.put(key, value)
      // 持久化
      await this.pref.flush()
      console.log(`保存preferences[${key} = ${value}]成功`)
    } catch (err) {
      console.error(`保存preferences[${key} = ${value}]失败`, JSON.stringify(err))
    }

  }

 6、new一下工具类,并导出

const preferenceUtil = new PreferenceUtil()

export default preferenceUtil as PreferenceUtil

 三、完整文件代码

import { preferences } from '@kit.ArkData'
import { CommonConstants } from '../constants/CommonConstants'

class PreferenceUtil{

  // 首选项实例
  private pref: preferences.Preferences | null = null

  /*
    * 初始化preferences实例
    * @context  应用上下文
   */
  async loadPreference(context: Context){
    try {
      this.pref = await preferences.getPreferences(context, CommonConstants.G_STORE)
      console.log(`preferences[${CommonConstants.G_STORE}]初始化成功`)
    } catch (err) {
      console.error(`preferences[${CommonConstants.G_STORE}]初始化失败`)
      console.error('err: ', JSON.stringify(err))
    }
  }

  /*
    * 销毁preferences实例 - 缓存、持久化文件一并销毁
    * @context  应用上下文
   */
  async delPreference(context: Context){
    try {
      await preferences.deletePreferences(context, CommonConstants.G_STORE)
      console.log(`preferences[${CommonConstants.G_STORE}]销毁成功`)
    } catch (err) {
      console.error(`preferences[${CommonConstants.G_STORE}]销毁失败`)
      console.error('err: ', JSON.stringify(err))
    }
  }

  /*
    * 从preferences实例中获取键对应的值
    * @key            健
    * @defaultValue   获取失败时,返回的值
   */
  async getPreferenceValue(key: string, defaultValue: preferences.ValueType): Promise<preferences.ValueType>{

    let value: preferences.ValueType = defaultValue

    // 获取对应的值之前,先判断preferences是否初始化完成
    if (!this.pref) {
      console.error(`preferences[${CommonConstants.G_STORE}]尚未初始化!`)
      return value
    }

    try {
      value = await this.pref.get(key, defaultValue)
      console.log(`读取preferences[${key} = ${value}]成功`)
    } catch (err) {
      console.error(`读取preferences[${key}]失败 `, JSON.stringify(err))
    }

    return value
  }

  /*
  * 从Preferences实例中写入数据
  * @key        健
  * @value      值
 */
  async putPreferenceValue(key: string, value: preferences.ValueType){

    // 写入数据之前,先判断preferences是否初始化完成
    if (!this.pref) {
      console.error(`preferences[${CommonConstants.G_STORE}]尚未初始化!`)
      return
    }

    try {
      await this.pref.put(key, value)
      // 持久化
      await this.pref.flush()
      console.log(`保存preferences[${key} = ${value}]成功`)
    } catch (err) {
      console.error(`保存preferences[${key} = ${value}]失败`, JSON.stringify(err))
    }

  }

}

const preferenceUtil = new PreferenceUtil()

export default preferenceUtil as PreferenceUtil

 常量类

export class CommonConstants {
  
  static readonly G_STORE: string = 'GreenTreasureStore'

  static readonly TOKEN: string = 'TOKEN'

  static readonly NULL_TOKEN: string = null

}

四、使用首选项工具类

1、在EntryAbility的生命周期函数中,初始化工具类

import { AbilityConstant, UIAbility, Want } from '@kit.AbilityKit';
import { hilog } from '@kit.PerformanceAnalysisKit';
import { window } from '@kit.ArkUI';
import PreferenceUtil from '../utils/PreferencesUtil';

export default class EntryAbility extends UIAbility {
  onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {
    hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onCreate');

    // 初始化preferences
    PreferenceUtil.loadPreference(this.context)

  }

  onDestroy(): void {
    hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onDestroy');

    // 销毁preferences
    //PreferenceUtil.delPreference(this.context)

  }

  ......

  }
}

2、在项目需要的地方,使用首选项工具类 

import PreferenceUtil from '../utils/PreferencesUtil';
import { CommonConstants } from '../constants/CommonConstants'

const getToken = async () => {
  return await PreferenceUtil.getPreferenceValue(
    CommonConstants.TOKEN, CommonConstants.NULL_TOKEN
  )
}

附录

贴一张官方的图


        文章结束,如有纰漏还望指正。可以在评论区留下自己的想法。思想的碰撞是自我提升的催化剂,可以激发创新和进步。

### HarmonyOS Next 开发首选项使用与配置 #### 首选项概述 HarmonyOS Next 提供了用户首选项Preferences)作为轻量级的数据持久化方案,适用于存储少量数据,例如用户的个性化设置或应用的配置信息[^3]。这些数据以键值对形式存储,其中键为字符串类型,而值可以是数字型、字符型、布尔型及其对应的数组类型。 #### 数据存储特点 - **轻量化设计**:由于所有数据会加载至内存中,因此不推荐存储大量数据集,以免造成过高的内存消耗。 - **快速访问**:得益于内存中的缓存机制,读取速度极快。 - **同步与异步操作支持**:开发者可以选择同步或异步方式完成数据的读写操作。 - **多种数据类型支持**:除了基本数据类型外,还支持其数组形式的存储。 #### 示例代码展示 以下是基于 HarmonyOS Next 的 Preference 使用示例: ```typescript // 导入必要的模块 import preferences from '@ohos.data.preferences'; async function saveData() { try { // 创建一个名为 'userSettings' 的偏好对象实例 const pref = await preferences.getPreferences('userSettings'); // 同步保存数据 pref.putBoolean('isDarkMode', true); pref.putString('themeColor', '#FFFFFF'); pref.putInt('fontSize', 18); // 异步保存更改到磁盘 await pref.flush(); console.log('Data saved successfully.'); } catch (error) { console.error(`Error saving data: ${error}`); } } async function readData() { try { // 获取已创建的偏好对象实例 const pref = await preferences.getPreferences('userSettings'); // 同步读取数据 const isDarkModeEnabled = pref.getBoolean('isDarkMode', false); // 默认值为false const themeColor = pref.getString('themeColor', ''); // 默认值为空字符串 const fontSize = pref.getInt('fontSize', 14); // 默认值为14 console.log(`Dark Mode Enabled: ${isDarkModeEnabled}, Theme Color: ${themeColor}, Font Size: ${fontSize}`); } catch (error) { console.error(`Error reading data: ${error}`); } } ``` 上述代码展示了如何通过 `preferences` 模块实现数据的存储与读取功能[^2]。 #### 封装优化 为了提高代码可维护性和复用性,可以通过封装简化 Preference 的调用逻辑。以下是一个简单的封装示例: ```typescript class UserPreferenceManager { private static instance: UserPreferenceManager; private prefs: any; constructor(prefName: string) { this.initPrefs(prefName); } public static getInstance(prefName: string): UserPreferenceManager { if (!UserPreferenceManager.instance) { UserPreferenceManager.instance = new UserPreferenceManager(prefName); } return UserPreferenceManager.instance; } private async initPrefs(prefName: string) { this.prefs = await preferences.getPreferences(prefName); } public async put(key: string, value: any): Promise<void> { switch (typeof value) { case 'boolean': this.prefs.putBoolean(key, value as boolean); break; case 'number': this.prefs.putInt(key, value as number); break; case 'string': this.prefs.putString(key, value as string); break; default: throw new Error('Unsupported type for preference storage.'); } await this.prefs.flush(); // 确保数据立即保存到磁盘 } public get<T>(key: string, defaultValue?: T): T | undefined { const result = this.prefs.get(key, defaultValue); return typeof result === 'undefined' ? defaultValue : result; } } const userManager = UserPreferenceManager.getInstance('userSettings'); userManager.put('isDarkMode', true).then(() => console.log('Setting updated.')); console.log(userManager.get<boolean>('isDarkMode')); // 输出true ``` 此封装类实现了单例模式并提供了通用方法来管理 Preference 存储的操作。 #### 总结 HarmonyOS Next 中的用户首选项是一种高效便捷的小规模数据存储工具,适合于保存应用程序的状态和用户偏好的简单场景。通过合理利用同步/异步 API 和自定义封装,能够显著提升开发效率和代码质量。 ---
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值