目录
前言
本专栏记录鸿蒙应用开发的一些知识,供鸿蒙开发者学习。笔者目前还是个小菜鸡,鸿蒙开发也是我看相关资料自学的,所以本文有些地方可能考虑不够周到,有些纰漏,就当抛砖引玉,还望读者海涵。目前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
)
}
附录
贴一张官方的图
文章结束,如有纰漏还望指正。可以在评论区留下自己的想法。思想的碰撞是自我提升的催化剂,可以激发创新和进步。