HarmonyOS Next 开发干货:Preferences 实现用户个性化设置存储 原创

全栈若城
发布于 2025-9-13 12:12
浏览
1收藏

@toc

前言

大家好,我是若城!欢迎来到 HarmonyOS Next 开发实战系列。本系列致力于为开发者提供实用的技术方案和即拿即用的代码示例,帮助大家快速掌握 HarmonyOS Next 应用开发中的核心功能。

本篇文章将深入讲解如何使用 Preferences 实现数据的持久化存储,让您的应用能够记住用户的个性化设置。让我们一起探索这个强大而实用的功能吧!

什么是 Preferences

Preferences(用户首选项) 是 HarmonyOS Next 提供的轻量级数据存储解决方案,具有以下特点:

核心特性

  • 键值对存储:采用 Key-Value 形式存储数据,简单高效
  • 数据类型支持:支持数字、字符串、布尔值及其对应的数组类型
  • 持久化存储:数据自动保存到 preferencesDir 路径下,应用重启后数据依然存在
  • 轻量级设计:适合存储用户配置、应用设置等轻量级数据

适用场景

  • 用户个性化设置(主题、语言等)
  • 应用配置信息
  • 用户偏好记录
  • 简单的状态保存

注意:本模块首批接口从 API version 9 开始支持,请确保您的开发环境版本符合要求。

案例演示

本案例将实现一个主题色设置功能,演示完整的数据持久化流程:

功能流程

  1. 首页展示:使用保存的主题色渲染界面
  2. 设置页面:提供多种主题色供用户选择
  3. 数据持久化:用户选择后自动保存设置
  4. 重启验证:关闭应用重新打开,设置依然生效

效果预览

如下图所示,用户可以从首页进入设置页面选择喜欢的主题色,设置完成后即使关闭应用重新打开,个性化设置依然保持不变,真正实现了数据的持久化存储。

HarmonyOS Next 开发干货:Preferences 实现用户个性化设置存储-鸿蒙开发者社区

HarmonyOS Next 开发干货:Preferences 实现用户个性化设置存储-鸿蒙开发者社区

HarmonyOS Next 开发干货:Preferences 实现用户个性化设置存储-鸿蒙开发者社区

代码实现

第一步:项目初始化配置

首先需要在 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 生命周期中调用初始化函数:

HarmonyOS Next 开发干货:Preferences 实现用户个性化设置存储-鸿蒙开发者社区

第二步:主页面样式加载

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();
}

代码解析:

  • aboutToAppearonPageShow 生命周期中调用 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}`);
        }
    }

关键步骤说明:

  1. 创建数据对象:将用户选择的颜色封装成 CustomStyle 对象
  2. 获取存储实例:通过 preferences.getPreferences() 获取名为 ‘customStyle’ 的存储实例
  3. 数据序列化:使用 JSON.stringify() 将对象转换为字符串格式
  4. 写入数据:调用 pref.put() 方法将数据写入存储
  5. 持久化保存:使用 pref.flush() 确保数据立即写入磁盘
  6. 用户反馈:通过 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 的完整使用流程:

核心要点

  1. 简单易用:Preferences 提供了简洁的 Key-Value 存储方式,适合轻量级数据持久化
  2. 生命周期集成:合理利用组件生命周期,确保数据的及时加载和应用
  3. 错误处理:完善的异常处理机制,提升应用的稳定性和用户体验
  4. 数据同步:使用 flush() 方法确保数据及时写入磁盘,避免数据丢失

实际应用价值

  • 用户体验提升:记住用户的个性化设置,提供一致的使用体验
  • 开发效率提高:简单的 API 设计,快速实现数据持久化功能
  • 应用场景广泛:适用于主题设置、用户偏好、应用配置等多种场景

最佳实践建议

  1. 合理规划数据结构:设计清晰的接口类型,便于维护和扩展
  2. 异步处理:使用 async/await 处理异步操作,避免阻塞主线程
  3. 用户反馈:及时给用户操作反馈,提升交互体验
  4. 错误处理:完善的错误处理和日志记录,便于问题排查

希望本文能够帮助您快速掌握 Preferences 的使用方法,在实际项目中灵活运用这一强大的数据存储功能!好了下课~~
更多干货分享请关注全栈若城

©著作权归作者所有,如需转载,请注明出处,否则将追究法律责任
1
收藏 1
回复
举报
回复
    相关推荐