HarmonyOS首选项数据持久化-存储主题

437 阅读4分钟

首选项数据持久化

帝心:全网首发HarmonyOS4.0教程(哔哩哔哩)创作者。致力于推广鸿蒙教程开发。

  1. 个人网站-鸿蒙学院
  2. 语雀笔记-编程视界
  3. 微信公众号:不多讲故事

首选项

简介

本示例使用@ohos.data.preferences 接口,展示了使用首选项持久化存储数据的功能。源码参考

效果预览

default主题Simple主题grey主题
default.pngsimple.pnggrey.png

使用说明

1.点击顶部titleBar的右侧切换按钮,弹出主题菜单,选择任意主题则切换相应的主题界面;

2.退出应用再重新进入,显示上一次退出前的主题界面。

开发步骤

1. 准备常量数据
  1. 三种主题名称组成的数组

  2. 三种主题数据:图标icon和对应name

  3. 存储主题数据的时候 要指定首选项对象即文件(数据库)名称

    一个项目可以有使用一个首选项对象存数据,也可以使用多个首选项文件分开存不同的数据。建议分门别类设计。

  4. 存储主题的时候,需要设计一个key值

    一个首选项对象(文件)可以存很多个键值对数据。根据key区分。

import { ImageAndName } from "../model/ImageAndName"export default class DxConstants{
​
  // 三种主题的名称
  static readonly THEME_NAMES:string[] = ['default','grey','Simple']
​
  // 三种主题数据
  static readonly themeDataArr: ImageAndName[][] = [
    [
      { image: "/image/model1/dialer.png", name: "dianhua" },
      { image: "/image/model1/shopping.png", name: "shangcheng" },
      { image: "/image/model1/notes.png", name: "beiwanglu" },
      { image: "/image/model1/settings.png", name: "shezhi" },
      { image: "/image/model1/camera.png", name: "xiangji" },
      { image: "/image/model1/gallery.png", name: "xiangce" },
      { image: "/image/model1/music.png", name: "yinyue" },
      { image: "/image/model1/video.png", name: "shipin" },
    ],
    [
      { image: "/image/model2/simplicityCall.png", name: "dianhua" },
      { image: "/image/model2/simplicityShop.png", name: "shangcheng" },
      { image: "/image/model2/simplicityNotes.png", name: "beiwanglu" },
      { image: "/image/model2/simplicitySetting.png", name: "shezhi" },
      { image: "/image/model2/simplicityCamera.png", name: "xiangji" },
      { image: "/image/model2/simplicityPhotos.png", name: "xiangce" },
      { image: "/image/model2/simplicityMusic.png", name: "yinyue" },
      { image: "/image/model2/simplicityVideo.png", name: "shipin" },
    ],
    [
      { image: "/image/model3/pwcall.png", name: "dianhua" },
      { image: "/image/model3/pwshop.png", name: "shangcheng" },
      { image: "/image/model3/pwnotes.png", name: "beiwanglu" },
      { image: "/image/model3/pwsetting.png", name: "shezhi" },
      { image: "/image/model3/pwcamera.png", name: "xiangji" },
      { image: "/image/model3/pwphotos.png", name: "xiangce" },
      { image: "/image/model3/pwmusic.png", name: "yinyue" },
      { image: "/image/model3/pwvideo.png", name: "shipin" },
    ]
  ]
​
  // 存储主题的首选项的 文件(数据库)名称
  static readonly PREFERENCES_THEME:string = "theme.db"// 存储主题的时候 key
  static readonly THEME_KEY:string = "themeModel"
}
2. 准备首选项工具类
  1. 设计成map数据结构,方便存多种首选项文件对象。后期存主题时,使用一个首选项对象,存字体大小时,可以使用另一个。如有其他需要使用不同的首选项对象时,灵活扩展。
  2. 首选项对象创建需要上下文对象和该文件数据库的name。设计好loadPreference()方法,创建好首选项对象后加入到map中。
  3. 设计保存数据和获取数据的方法。 既然设计逻辑为该项目有多个首选项对象,那么在 保存/获取 数据的时候就需要确定从 哪个首选项对象 身上 存储/获取 哪个key
// 首选项工具栏,提供首选项增上改查功能
import { preferences } from '@kit.ArkData'
import { Context } from '@ohos.arkui.UIContext'class PreferencesUtil {
  // 准备一个map, 用来存多个首选项对象
  preMap: Map<string, preferences.Preferences> = new Map()
​
  // 加载 首选项对象
  loadPreference(context: Context, name: string) {
    try {
      // 该接口 第二个参数 在next修改为配置项 而非字符串
      let pre: preferences.Preferences = preferences.getPreferencesSync(context, { name })
      // 存到首选项 map中
      this.preMap.set(name, pre)
      console.log('PreferencesUtil', `加载Preferences【${name}】成功`)
    } catch (e) {
      console.log('PreferencesUtil', `加载Preferences【${name}】失败`, JSON.stringify(e))
    }
  }
​
  // 保存数据
   putPreferenceVal(preferenceName: string, key: string, value: preferences.ValueType) {
    if (!this.preMap.has(preferenceName)) {
      console.log('PreferencesUtil', `加载Preferences【${preferenceName}】尚未初始化`)
      return
    }
    try {
      // 从数组中获取该首选项对象
      let pref = this.preMap.get(preferenceName)
      // 写入数据
      pref?.putSync(key, value)
      // 刷盘
      pref?.flush()
      console.log('PreferencesUtil', `保存【${preferenceName}】-【${key}】-【${value}】成功`)
    } catch (e) {
      console.log('PreferencesUtil', `保存【${preferenceName}】-【${key}】-【${value}】失败`, JSON.stringify(e))
    }
  }
​
  // 获取数据
  getPreferenceVal(preferenceName: string, key: string, defaultVal: preferences.ValueType){
    if (!this.preMap.has(preferenceName)) {
      console.log('PreferencesUtil', `加载Preferences【${preferenceName}】尚未初始化`)
      return
    }
    try {
      let pref = this.preMap.get(preferenceName)
      let val = pref?.getSync(key, defaultVal)
      console.log('PreferencesUtil', `读取【${preferenceName}】-【${key}】-【${val}】成功`)
      return val
    }catch (e){
      console.log('PreferencesUtil', `读取【${preferenceName}】-【${key}】失败`,JSON.stringify(e))
      // try和catch都要有返回
      return defaultVal
    }
  }
}
​
export default new PreferencesUtil()
3. 入口类中创建首选项对象
  onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {
    // 初始化首选项
    let context = this.context
    // 存储主题的 首选项文件放到 map中
    PreferencesUtil.loadPreference(context,DxConstants.PREFERENCES_THEME)
  }
4. 在UI中使用
  • 切换主题:在首页预先设置好几套主体数据,使用preferences.getPreferences获取使用Preferences对象,调用Preferences.get() 读取缓存中的参数,得到当前应该展示哪一套主体。每次点击切换按钮都会调用Preferences.put()来重新修改参数,然后使用 Preferences.flush()保存并刷新文件内容。 源码参考:Index.ets
import DxConstants from "../common/DxConstants";
import PreferencesUtil from "../common/PreferencesUtil";
import { ImageAndName } from "../model/ImageAndName";
​
​
@Entry
@Component
struct Index {
  @StorageProp("info") message: string = ""
  // 当前页面展示的数据
  @State theme: ImageAndName[] = DxConstants.themeDataArr[0]
  @State themeName: string = DxConstants.THEME_KEY[0]
​
  // 页面加载先查看上一次的主题是什么
  aboutToAppear(): void {
    this.themeName = PreferencesUtil.getPreferenceVal(
      DxConstants.PREFERENCES_THEME,
      DxConstants.THEME_KEY,
      DxConstants.THEME_NAMES[0]
    ) as string
    // 根据 modelName 获取索引值
    let index = DxConstants.THEME_NAMES.indexOf(this.themeName)
    // 初始化当前模型数组
    this.theme = DxConstants.themeDataArr[index]
  }
​
  // 修改当前显示模式
  changeTheme(index: number) {
    // 主题名称
    this.themeName = DxConstants.THEME_NAMES[index]
    // 主题数组
    this.theme = DxConstants.themeDataArr[index]
    // 持久化存储
    PreferencesUtil.putPreferenceVal(
      DxConstants.PREFERENCES_THEME,
      DxConstants.THEME_KEY,
      DxConstants.THEME_NAMES[index]
    )
  }
​
  build() {
    Column({ space: 30 }) {
      Text(this.message).fontColor("#fff50909")
      Divider().color(Color.Red)
      Row() {
        Text("主题:"+this.themeName)
          .fontSize(20)
          .layoutWeight(5)
          .padding({ left: 10 })
          .fontColor(Color.White)
          .fontWeight(FontWeight.Bold)
        Image($r('app.media.change'))
          .key('changeBtn')
          .id('changeBtn')
          .height(30)
          .layoutWeight(1)
          .objectFit(ImageFit.ScaleDown)
          .bindMenu([
            {
              value: DxConstants.THEME_NAMES[0],
              action: () => {
                // change  and save model0 :default
                this.changeTheme(0)
              }
            },
            {
              value: DxConstants.THEME_NAMES[1],
              action: () => {
                // change  and save model1 :simplicity
                this.changeTheme(1)
​
              }
            },
            {
              value: DxConstants.THEME_NAMES[2],
              action: () => {
                // change  and save model2 :pomelo
                this.changeTheme(2)
              }
            }
          ])
      }
      .width('100%')
      .height(50)
      .backgroundColor('#0D9FFB')
​
      Grid() {
        ForEach(this.theme, (item: ImageAndName) => {
          GridItem() {
            Column() {
              Image(item.image)
                .width(70)
                .height(70)
                .padding(10)
                .objectFit(ImageFit.Fill)
              Text(item.name).fontSize(15)
            }
            .width(90)
            .height(90)
          }
        }, (item: ImageAndName) => JSON.stringify(item))
      }
      .rowsGap(10)
      .width('100%')
      .columnsGap(10)
      .layoutWeight(1)
      .padding({ top: 20 })
      .backgroundColor('#e5e5e5')
      .columnsTemplate('1fr 1fr 1fr 1fr')
    }
    .width('100%')
    .height('100%')
    .backgroundColor($r('app.color.theme_color'))
  }
}

相关权限

不涉及。

依赖

不涉及。

约束与限制

1.本示例仅支持标准系统上运行,支持设备:纯血鸿蒙华为手机、模拟器。

2.HarmonyOS系统:HarmonyOS NEXT Developer。

3.DevEco Studio版本:DevEco Studio NEXT Developer。