
HarmonyOS Next 开发干货:Preferences 实现用户个性化设置存储 原创
@toc
前言
大家好,我是若城!欢迎来到 HarmonyOS Next 开发实战系列。本系列致力于为开发者提供实用的技术方案和即拿即用的代码示例,帮助大家快速掌握 HarmonyOS Next 应用开发中的核心功能。
本篇文章将深入讲解如何使用 Preferences 实现数据的持久化存储,让您的应用能够记住用户的个性化设置。让我们一起探索这个强大而实用的功能吧!
什么是 Preferences
Preferences(用户首选项) 是 HarmonyOS Next 提供的轻量级数据存储解决方案,具有以下特点:
核心特性
- 键值对存储:采用 Key-Value 形式存储数据,简单高效
- 数据类型支持:支持数字、字符串、布尔值及其对应的数组类型
- 持久化存储:数据自动保存到
preferencesDir
路径下,应用重启后数据依然存在 - 轻量级设计:适合存储用户配置、应用设置等轻量级数据
适用场景
- 用户个性化设置(主题、语言等)
- 应用配置信息
- 用户偏好记录
- 简单的状态保存
注意:本模块首批接口从 API version 9 开始支持,请确保您的开发环境版本符合要求。
案例演示
本案例将实现一个主题色设置功能,演示完整的数据持久化流程:
功能流程
- 首页展示:使用保存的主题色渲染界面
- 设置页面:提供多种主题色供用户选择
- 数据持久化:用户选择后自动保存设置
- 重启验证:关闭应用重新打开,设置依然生效
效果预览
如下图所示,用户可以从首页进入设置页面选择喜欢的主题色,设置完成后即使关闭应用重新打开,个性化设置依然保持不变,真正实现了数据的持久化存储。
代码实现
第一步:项目初始化配置
首先需要在 EntryAbility
中进行初始化配置,设置默认的主题色。这一步骤确保应用首次启动时有默认的样式配置。
1.1 导入必要的模块
在 EntryAbility.ets
文件中导入相关依赖:
import { preferences } from '@kit.ArkData';
import {CustomStyle } from "../utils/types"
import { BusinessError } from '@kit.BasicServicesKit';
1.2 定义类型接口
在 ../utils/types
文件中定义相关的 TypeScript 接口:
export interface CustomStyle{
setBgColor :string
}
export interface autoColor{color: string, name: string}
1.3 实现初始化函数
在 EntryAbility.ets
中实现自定义样式的初始化逻辑:
async initCustomStyle(): Promise<void> {
try {
const pref = await preferences.getPreferences(this.context, 'customStyle');
const styleData = await pref.get('styleData', '');
if (!styleData) {
hilog.info(DOMAIN, 'testTag', 'No custom style found, saving default style.');
const defaultStyle: CustomStyle = {
setBgColor: '#F9F7F5',
};
await pref.put('styleData', JSON.stringify(defaultStyle));
await pref.flush();
hilog.info(DOMAIN, 'testTag', 'Default custom style has been saved successfully.');
} else {
hilog.info(DOMAIN, 'testTag', 'Custom style already exists.');
}
} catch (err) {
const error = err as BusinessError;
hilog.error(DOMAIN, 'testTag', `Failed to initialize custom style. Code is ${error.code}, message is ${error.message}`);
}
}
1.4 生命周期集成
在 onWindowStageCreate
生命周期中调用初始化函数:
第二步:主页面样式加载
2.1 导入依赖模块
在主页面文件中引入必要的包:
import { preferences } from '@kit.ArkData';
import {CustomStyle } from "../utils/types"
import { BusinessError } from '@kit.BasicServicesKit';
2.2 实现样式加载逻辑
编写加载和应用主题色的核心函数:
@State autoBgColor:string =''
async loadStyle() {
try {
const pref = await preferences.getPreferences(getContext(this), 'customStyle');
const styleDataString = await pref.get('styleData', '');
if (styleDataString) {
const styleData = JSON.parse(styleDataString as string) as CustomStyle;
this.autoBgColor = styleData.setBgColor;
}
} catch (err) {
const error = err as BusinessError;
console.error(`Failed to load custom style. Code is ${error.code}, message is ${error.message}`);
}
}
aboutToAppear(): void {
this.loadStyle();
}
onPageShow(): void {
this.loadStyle();
}
代码解析:
- 在
aboutToAppear
和onPageShow
生命周期中调用loadStyle()
方法 - 通过
preferences.getPreferences()
获取存储实例 - 使用
pref.get()
方法读取已保存的样式数据 - 将读取到的 JSON 字符串解析为对象并应用到界面
第三步:主题设置页面实现
3.1 完整页面代码
为了便于理解和使用,以下是主题设置页面的完整实现代码:
import {autoColor,CustomStyle } from "../utils/types"
import { preferences } from '@kit.ArkData';
import { BusinessError } from '@kit.BasicServicesKit';
import { promptAction, router, Router } from "@kit.ArkUI";
@Entry
@Component
struct Theme {
// 定义18个不同的颜色数据
private colorData: autoColor[] = [
{ color: '#FF8C00', name: 'DarkOrange' },
{ color: '#FF6347', name: 'Tomato' },
{ color: '#32CD32', name: 'LimeGreen' },
{ color: '#1E90FF', name: 'DodgerBlue' },
{ color: '#FF1493', name: 'DeepPink' },
{ color: '#9370DB', name: 'MediumPurple' },
{ color: '#FFD700', name: 'Gold' },
{ color: '#20B2AA', name: 'LightSeaGreen' },
{ color: '#FF4500', name: 'OrangeRed' },
{ color: '#8A2BE2', name: 'BlueViolet' },
{ color: '#00CED1', name: 'DarkTurquoise' },
{ color: '#FF69B4', name: 'HotPink' },
{ color: '#7FFF00', name: 'Chartreuse' },
{ color: '#DC143C', name: 'Crimson' },
{ color: '#00BFFF', name: 'DeepSkyBlue' },
{ color: '#DA70D6', name: 'Orchid' },
{ color: '#FFA500', name: 'Orange' },
{ color: '#40E0D0', name: 'Turquoise' }
]
// 定义应用色
async handleApplyBgColor(color:string){
const autoColor:CustomStyle ={
setBgColor:color
}
try {
// 获取首选项实例
const pref = await preferences.getPreferences(getContext(this), 'customStyle');
// 将样式对象转换为字符串并存储
await pref.put('styleData', JSON.stringify(autoColor));
// 刷新数据到磁盘
await pref.flush();
console.info('自定义样式设置成功~~');
this.getUIContext().getPromptAction().showToast({
message: "自定义样式设置成功 ~~",
duration: 2000,
showMode: promptAction.ToastShowMode.DEFAULT,
bottom: 80
});
} catch (err) {
const error = err as BusinessError;
this.getUIContext().getPromptAction().showToast({
message: "自定义样式设置失败 ~~",
duration: 2000,
showMode: promptAction.ToastShowMode.DEFAULT,
bottom: 80
});
console.error(`设置失败 ${error.code}, ${error.message}`);
}
}
@Builder
ColorCard(colorInfo:autoColor) {
Column() {
// 颜色展示区域
Row()
.width('100%')
.height(60)
.backgroundColor(colorInfo.color)
.borderRadius({
topLeft: 8,
topRight: 8,
bottomLeft: 0,
bottomRight: 0
})
// 信息展示区域
Column() {
Text(colorInfo.color)
.fontSize(12)
.fontWeight(FontWeight.Bold)
.fontColor('#333333')
.margin({ top: 6 })
Text(colorInfo.name)
.fontSize(10)
.fontColor('#666666')
.margin({ top: 2, bottom: 6 })
}
.width('100%')
.backgroundColor('#FFFFFF')
.borderRadius({
topLeft: 0,
topRight: 0,
bottomLeft: 8,
bottomRight: 8
})
}
.width('100%')
.backgroundColor('#FFFFFF')
.borderRadius(8)
.shadow({
radius: 4,
color: '#1A000000',
offsetX: 0,
offsetY: 1
})
.onClick(()=>{
this.handleApplyBgColor(colorInfo.color)
})
}
build() {
Column() {
Row(){
Button('返回').onClick(()=>{
router.replaceUrl({
url:'pages/Index'
})
})
}
Text('颜色主题')
.fontSize(20)
.fontWeight(FontWeight.Bold)
.margin({ top: 20, bottom: 16 })
.fontColor('#333333')
// 使用Grid布局,4列显示
Grid() {
ForEach(this.colorData, (item: autoColor, index: number) => {
GridItem() {
this.ColorCard(item)
}
.padding(4)
})
}
.columnsTemplate('1fr 1fr 1fr 1fr') // 4列等宽
.rowsGap(8)
.columnsGap(8)
.padding({ left: 12, right: 12 })
.layoutWeight(1)
}
.height('100%')
.width('100%')
.backgroundColor('#F8F8F8')
}
}
3.2 核心功能解析
主题色应用函数 - 数据持久化的关键实现:
// 定义应用色
async handleApplyBgColor(color:string){
const autoColor:CustomStyle ={
setBgColor:color
}
try {
// 获取首选项实例
const pref = await preferences.getPreferences(getContext(this), 'customStyle');
// 将样式对象转换为字符串并存储
await pref.put('styleData', JSON.stringify(autoColor));
// 刷新数据到磁盘
await pref.flush();
console.info('自定义样式设置成功~~');
this.getUIContext().getPromptAction().showToast({
message: "自定义样式设置成功 ~~",
duration: 2000,
showMode: promptAction.ToastShowMode.DEFAULT,
bottom: 80
});
} catch (err) {
const error = err as BusinessError;
this.getUIContext().getPromptAction().showToast({
message: "自定义样式设置失败 ~~",
duration: 2000,
showMode: promptAction.ToastShowMode.DEFAULT,
bottom: 80
});
console.error(`设置失败 ${error.code}, ${error.message}`);
}
}
关键步骤说明:
- 创建数据对象:将用户选择的颜色封装成
CustomStyle
对象 - 获取存储实例:通过
preferences.getPreferences()
获取名为 ‘customStyle’ 的存储实例 - 数据序列化:使用
JSON.stringify()
将对象转换为字符串格式 - 写入数据:调用
pref.put()
方法将数据写入存储 - 持久化保存:使用
pref.flush()
确保数据立即写入磁盘 - 用户反馈:通过 Toast 提示用户操作结果
精华提炼
说白了preferences
的持久化存储主要就是 一个存, 一个取
存
// 获取首选项实例
const pref = await preferences.getPreferences(getContext(this), 'customStyle');
// 将样式对象转换为字符串并存储
await pref.put('styleData', JSON.stringify(autoColor));
// 刷新数据到磁盘
await pref.flush();
取
const pref = await preferences.getPreferences(getContext(this), 'customStyle');
const styleDataString = await pref.get('styleData', '');
简单吧~~, 掌握好持久化存储的使用方法, 可以做很多事情哦
总结
通过本文的学习,我们掌握了 HarmonyOS Next 中 Preferences 的完整使用流程:
核心要点
- 简单易用:Preferences 提供了简洁的 Key-Value 存储方式,适合轻量级数据持久化
- 生命周期集成:合理利用组件生命周期,确保数据的及时加载和应用
- 错误处理:完善的异常处理机制,提升应用的稳定性和用户体验
- 数据同步:使用
flush()
方法确保数据及时写入磁盘,避免数据丢失
实际应用价值
- 用户体验提升:记住用户的个性化设置,提供一致的使用体验
- 开发效率提高:简单的 API 设计,快速实现数据持久化功能
- 应用场景广泛:适用于主题设置、用户偏好、应用配置等多种场景
最佳实践建议
- 合理规划数据结构:设计清晰的接口类型,便于维护和扩展
- 异步处理:使用 async/await 处理异步操作,避免阻塞主线程
- 用户反馈:及时给用户操作反馈,提升交互体验
- 错误处理:完善的错误处理和日志记录,便于问题排查
希望本文能够帮助您快速掌握 Preferences 的使用方法,在实际项目中灵活运用这一强大的数据存储功能!好了下课~~
更多干货分享请关注全栈若城
