HarmonyOS官网案例解析——保存应用数据

news/2024/7/21 11:05:11 标签: harmonyos, 华为

介绍

本篇Codelab将介绍如何使用基础组件Slider,通过拖动滑块调节应用内字体大小。要求完成以下功能:

  1. 实现两个页面的UX:主页面和字体大小调节页面。
  2. 拖动滑块改变字体大小系数,列表页和调节页面字体大小同步变化。往右拖动滑块字体变大,反之变小。
  3. 字体大小支持持久化存储,再次启动时,应用内字体仍是调节后的字体大小。

最终效果图如图所示:

https://gitee.com/runitwolf/sloop-pic-go/raw/master/image/202312212240377.gif

一、相关概念

  • 字体大小调节原理:通过组件Slider滑动,获取滑动数值,将这个值通过首选项进行持久化,页面的字体通过这个值去改变大小。
  • 首选项:首选项为应用提供Key-Value键值型的数据处理能力,支持应用持久化轻量级数据,并对其修改和查询。

二、完整实例

gitee源码地址

ps:官网的案例很简单,但是有很多地方值得我们借鉴。

官方对案例解析

<HarmonyOS第一课>保存应用数据

三、零基础实战开发

一、用数组的方法值得借鉴

  1. 现新建一个bean类
export default class SettingData{
  settingName:string
  settingImage:Resource
}
  1. 新建HomeViewModel.etx
import SettingData from './SettingData'

export class HomeViewModel {
  settingArr: SettingData[] = []

  initSettingData(): SettingData[] {
    if (this.settingArr.length === 0) {
      let settingData = new SettingData()
      settingData.settingName = '显示和亮度'
      settingData.settingImage = $r('app.media.ic_display_and_brightness')
      this.settingArr.push(settingData)

      settingData = new SettingData();
      settingData.settingName = '声音';
      settingData.settingImage = $r('app.media.ic_voice');
      this.settingArr.push(settingData);

      settingData = new SettingData();
      settingData.settingName = '应用管理';
      settingData.settingImage = $r('app.media.ic_app_management');
      this.settingArr.push(settingData);

      settingData = new SettingData();
      settingData.settingName = '存储';
      settingData.settingImage = $r('app.media.ic_storage');
      this.settingArr.push(settingData);

      settingData = new SettingData();
      settingData.settingName = '隐私';
      settingData.settingImage = $r('app.media.ic_privacy');
      this.settingArr.push(settingData);

      settingData = new SettingData();
      settingData.settingName = '设置字体大小';
      settingData.settingImage = $r('app.media.ic_setting_the_font_size');
      this.settingArr.push(settingData);

    }
    return this.settingArr
  }
}
export default new HomeViewModel()

在index.ets中直接使用即可使用方法如下

 settingArr = HomeViewModel.initSettingData();
 //settingArr[x],x为数组的索引,直接使用就可以获取设定的数据

1."标题"页面实现

import { TitleBarComponent } from '../view/TitleBarComponent'

@Entry
@Component
struct Index {
  build() {
    Column() {
      TitleBarComponent({ isBack: false, title: '设置' })
    }
    .width('100%')
    .height('100%')
  }
}
import router from '@ohos.router'
@Component
export struct TitleBarComponent {
  isBack:boolean = true
  title:string = ''

  build() {
    Row() {
      if (this.isBack){
        Image($r('app.media.ic_public_back'))
          .width(24)
          .height(24)
          .margin({ right: 4 })
          .onClick(() => {
            router.back()
          })
      }
      Text(this.title)
        .fontColor(Color.Black)
        .fontSize($r('sys.float.ohos_id_text_size_headline8'))
        .fontWeight(FontWeight.Medium)
        .margin({ left: 8 })
    }
    .width('100%')
    .height('7.2%')
    .padding({ left: 16 })
  }
}

在这里插入图片描述

2."显示和亮度"页面实现

import SettingItemComponent from '../view/SettingItemComponent'
import { TitleBarComponent } from '../view/TitleBarComponent'
import HomeViewModel from '../viewModel/HomeViewModel'
import SettingData from '../viewModel/SettingData'

@Entry
@Component
struct Index {
  settingArr: SettingData[] = HomeViewModel.initSettingData()
  @State changeFontSize: number = 16

  build() {
    Column() {
      ...
      //显示和亮度
      Row() {
        SettingItemComponent({
          setting: this.settingArr[0],
          changeFontSize: this.changeFontSize,
          itemClick: () => {
            //TODO
          }
        })
      }
      .blockBackground('1.5%')
    }
    .backgroundColor('#f1f3f5')
    .width('100%')
    .height('100%')
  }
}

@Extend(Row) function blockBackground (marginTop: string) {
  .backgroundColor(Color.White)
  .borderRadius(24)
  .margin({ top: marginTop })
  .width('93.3%')
  .padding({ top: 4, bottom: 4 })
}

思考题:这里的changeFontSize变量为什么需要用@State进行修饰,而settingArr又为什么不需要?

3."声音"页面实现

import SettingItemComponent from '../view/SettingItemComponent'
import { TitleBarComponent } from '../view/TitleBarComponent'
import HomeViewModel from '../viewModel/HomeViewModel'
import SettingData from '../viewModel/SettingData'

@Entry
@Component
struct Index {

  build() {
    Column() {
      TitleBarComponent({ isBack: false, title: '设置' })
      ...
      //声音
      Row() {
        SettingItemComponent({
          setting: this.settingArr[1],
          changeFontSize: this.changeFontSize,
          itemClick: () => {
            //TODO
          }
        })
      }
      .blockBackground('1.5%')
    }
    .backgroundColor('#f1f3f5')
    .width('100%')
    .height('100%')
  }
}

4.“应用管理”、"存储"等列表页面实现

import SettingItemComponent from '../view/SettingItemComponent'
import { TitleBarComponent } from '../view/TitleBarComponent'
import HomeViewModel from '../viewModel/HomeViewModel'
import SettingData from '../viewModel/SettingData'

@Entry
@Component
struct Index {
  settingArr: SettingData[] = HomeViewModel.initSettingData()
  @State changeFontSize: number = 16

  build() {
    Column() {
     ...
      Row(){
        this.SettingItems()
      }
      .blockBackground('1.5%')
    }
    ...
  }

  @Builder SettingItems(){
    List(){
      ForEach(this.settingArr.splice(2,6),(item:SettingData,index:number)=>{
        ListItem(){
          SettingItemComponent({setting:item,changeFontSize:this.changeFontSize,itemClick:()=>{
            //TODO
          }})
        }
      }, (item:SettingData,index:number)=>JSON.stringify(item)+index)
    }
  }
}

5."设置字体大小"点击事件跳转

import router from '@ohos.router'
import PreferencesUtil from '../common/database/PreferencesUtil'
import SettingItemComponent from '../view/SettingItemComponent'
import { TitleBarComponent } from '../view/TitleBarComponent'
import HomeViewModel from '../viewModel/HomeViewModel'
import SettingData from '../viewModel/SettingData'

@Entry
@Component
struct Index {
  settingArr: SettingData[] = HomeViewModel.initSettingData()
  @State changeFontSize: number = 16

  onPageShow(){
    PreferencesUtil.getChangeFontSize().then((value)=>{
      this.changeFontSize = value
    })
  }

  build() {
	....
  @Builder SettingItems(){
    List(){
      ForEach(this.settingArr.splice(2,6),(item:SettingData,index:number)=>{
        ListItem(){
          SettingItemComponent({setting:item,changeFontSize:this.changeFontSize,itemClick:()=>{
            if (index === 3) {
              router.pushUrl({
                url:"pages/SetFontSizePage"
              })
            }
          }})
        }
      }, (item:SettingData,index:number)=>JSON.stringify(item)+index)
    }
  }
}

在pages目录下新建SetFontSizePage子组件

import  PreferencesUtil  from '../common/database/PreferencesUtil'
import { ItemComponent } from '../view/ItemComponent'
import { SliderLayout } from '../view/SliderLayout'
import { TitleBarComponent } from '../view/TitleBarComponent'
import HomeViewModel from '../viewModel/HomeViewModel'
import SettingData from '../viewModel/SettingData'

@Entry
@Component
struct SetFontSizePage {

  build() {
    Column() {
      TitleBarComponent({ title: '字体大小设置' })
    }
    .width('100%')
    .height('100%')
  }
}

ps:官网的案例不太友好,我们在官网的页面基础上进行功能及界面简化

6.SetFontSizePage页面创建数据

我们之前在首页HomeViewModel模型下创建过数据,我们沿用HomeViewModel模型,继续创建想要的数据

import SettingData from './SettingData'

export class HomeViewModel {
  ...
  fontSizeArr: SettingData[] = []
  ...

  initFontSizeData():SettingData[]{
    this.fontSizeArr = new Array();
    let fontSizeArr = new SettingData()
    fontSizeArr.settingName = '11111111111111111111'
    this.fontSizeArr.push(fontSizeArr)
    fontSizeArr = new SettingData()
    fontSizeArr.settingName = '22222222222222222222'
    this.fontSizeArr.push(fontSizeArr)
    fontSizeArr = new SettingData()
    fontSizeArr.settingName = '33333333333333333333'
    this.fontSizeArr.push(fontSizeArr)
    fontSizeArr = new SettingData()
    fontSizeArr.settingName = '44444444444444444444'
    this.fontSizeArr.push(fontSizeArr)

    return this.fontSizeArr
  }
}
export default new HomeViewModel()

7.写SetFontSizePage中list页面

import  PreferencesUtil  from '../common/database/PreferencesUtil'
import { ItemComponent } from '../view/ItemComponent'
import { SliderLayout } from '../view/SliderLayout'
import { TitleBarComponent } from '../view/TitleBarComponent'
import HomeViewModel from '../viewModel/HomeViewModel'
import SettingData from '../viewModel/SettingData'

@Entry
@Component
struct SetFontSizePage {
  contentArr: SettingData[] = HomeViewModel.initFontSizeData()
  @State changeFontSize: number = 0

  onPageShow(){
    PreferencesUtil.getChangeFontSize().then((value)=>{
      this.changeFontSize = value
    })
  }

  build() {
    Column() {
      TitleBarComponent({ title: '字体大小设置' })
      List() {
        ForEach(this.contentArr, (item: SettingData, index: number) => {
          ListItem() {
            ItemComponent({ contentArr: item, changeFontSize: this.changeFontSize })
          }

        }, (item: SettingData, index: number) => JSON.stringify(item) + index)
      }
    }
    .width('100%')
    .height('100%')
  }
}
import SettingData from '../viewmodel/SettingData'
@Component
export struct ItemComponent {

  contentArr: SettingData
  @Prop changeFontSize:number

  build() {
    Column() {
      Text(this.contentArr.settingName)
        .fontSize(this.changeFontSize)
        .fontColor('#182431')
        .fontWeight(FontWeight.Medium)
        .height(48)
        .width('100%')
        .textAlign(TextAlign.Center)
    }
  }
}

看看list的效果图:

8.写SetFontSizePage进度条

import  PreferencesUtil  from '../common/database/PreferencesUtil'
import { ItemComponent } from '../view/ItemComponent'
import { SliderLayout } from '../view/SliderLayout'
import { TitleBarComponent } from '../view/TitleBarComponent'
import HomeViewModel from '../viewModel/HomeViewModel'
import SettingData from '../viewModel/SettingData'

@Entry
@Component
struct SetFontSizePage {
	...
  build() {
    Column() {
     ...
      List() {
        ...
      }
      SliderLayout({changeFontSize:$changeFontSize})
    }
    ...
  }
}
import PreferencesUtil from '../common/database/PreferencesUtil'
@Component
export struct SliderLayout {

  @Link changeFontSize:number

  build() {
    Column() {
      Text('文字大小')
        .fontSize(14)
        .fontColor('#182431')
        .fontWeight(FontWeight.Medium)

      Row(){
        Text('A')
          .fontColor('#182431')
          .fontSize(20)
          .fontWeight(FontWeight.Medium)
          .textAlign(TextAlign.End)
          .width('12.5%')
          .padding({right:9})

        Slider({
          value:this.changeFontSize,
          min:14,
          max:22,
          step:2,
          style:SliderStyle.InSet
        })
          .showSteps(true)
          .width('75%')
          .onChange((value:number)=>{
            this.changeFontSize = value
          })

        Text('A')
          .fontColor('#182431')
          .fontSize(20)
          .fontWeight(FontWeight.Medium)
          .width('12.5%')
          .padding({left:9})
      }

    }
  }
}

运行后效果图如下:
在这里插入图片描述

至此,我们发现滑动进度条,页面的大小变了,但是返回页面后再次进入,数据没有保存。

四、保存应用数据

<HarmonyOS第一课>保存应用数据(官网文档)

根据官网的文档,我们新建PreferencesUtil工具类

import dataPreferences from '@ohos.data.preferences';
import { GlobalContext } from '../utils/GlobalContext';
import Logger from '../utils/Logger';

const TAG = '[PreferencesUtil]';
const PREFERENCES_NAME = 'myPreferences';
const KEY_APP_FONT_SIZE = 'appFontSize';

/**
 * The PreferencesUtil provides preferences of create, save and query.
 */
export class PreferencesUtil {
  createFontPreferences(context: Context) {
    let fontPreferences: Function = (() => {
      let preferences: Promise<dataPreferences.Preferences> = dataPreferences.getPreferences(context, PREFERENCES_NAME);
      return preferences;
    });
    GlobalContext.getContext().setObject('getFontPreferences', fontPreferences);
  }

  saveDefaultFontSize(fontSize: number) {
    let getFontPreferences: Function = GlobalContext.getContext().getObject('getFontPreferences') as Function;
    getFontPreferences().then((preferences: dataPreferences.Preferences) => {
      preferences.has(KEY_APP_FONT_SIZE).then(async (isExist: boolean) => {
        Logger.info(TAG, 'preferences has changeFontSize is ' + isExist);
        if (!isExist) {
          await preferences.put(KEY_APP_FONT_SIZE, fontSize);
          preferences.flush();
        }
      }).catch((err: Error) => {
        Logger.error(TAG, 'Has the value failed with err: ' + err);
      });
    }).catch((err: Error) => {
      Logger.error(TAG, 'Get the preferences failed, err: ' + err);
    });
  }

  saveChangeFontSize(fontSize: number) {
    let getFontPreferences: Function = GlobalContext.getContext().getObject('getFontPreferences') as Function;
    getFontPreferences().then(async (preferences: dataPreferences.Preferences) => {
      await preferences.put(KEY_APP_FONT_SIZE, fontSize);
      preferences.flush();
    }).catch((err: Error) => {
      Logger.error(TAG, 'put the preferences failed, err: ' + err);
    });
  }

  async getChangeFontSize() {
    let fontSize: number = 0;
    let getFontPreferences: Function = GlobalContext.getContext().getObject('getFontPreferences') as Function;
    fontSize = await (await getFontPreferences()).get(KEY_APP_FONT_SIZE, fontSize);
    return fontSize;
  }

  async deleteChangeFontSize() {
    let getFontPreferences: Function = GlobalContext.getContext().getObject('getFontPreferences') as Function;
    const preferences: dataPreferences.Preferences = await getFontPreferences();
    let deleteValue = preferences.delete(KEY_APP_FONT_SIZE);
    deleteValue.then(() => {
      Logger.info(TAG, 'Succeeded in deleting the key appFontSize.');
    }).catch((err: Error) => {
      Logger.error(TAG, 'Failed to delete the key appFontSize. Cause: ' + err);
    });
  }
}

export default new PreferencesUtil();
export class GlobalContext {
  private constructor() { }
  private static instance: GlobalContext;
  private _objects = new Map<string, Object>();

  public static getContext(): GlobalContext {
    if (!GlobalContext.instance) {
      GlobalContext.instance = new GlobalContext();
    }
    return GlobalContext.instance;
  }

  getObject(value: string): Object | undefined {
    return this._objects.get(value);
  }

  setObject(key: string, objectClass: Object): void {
    this._objects.set(key, objectClass);
  }
}

1.使用前提

需要在entryAbility的onCreate方法获取首选项实例

import UIAbility from '@ohos.app.ability.UIAbility';
import hilog from '@ohos.hilog';
import window from '@ohos.window';
import Logger from '../common/utils/Logger';
import { GlobalContext } from '../common/utils/GlobalContext';
import PreferencesUtil from '../common/database/PreferencesUtil'

export default class EntryAbility extends UIAbility {
  onCreate(want, launchParam) {
 
    PreferencesUtil.createFontPreferences(this.context);
  }
	...
}

2.保存数据

在应用刚启动时,设置字体默认大小

import UIAbility from '@ohos.app.ability.UIAbility';
import hilog from '@ohos.hilog';
import window from '@ohos.window';
import Logger from '../common/utils/Logger';
import { GlobalContext } from '../common/utils/GlobalContext';
import PreferencesUtil from '../common/database/PreferencesUtil'

export default class EntryAbility extends UIAbility {
  onCreate(want, launchParam) {
    ...
    // 设置字体默认大小
    PreferencesUtil.saveDefaultFontSize(16);
  }
	...
}

在滑动进度条后,保存进度条设置的字体大小

import PreferencesUtil from '../common/database/PreferencesUtil'
@Component
export struct SliderLayout {

  @Link changeFontSize:number

  build() {
    ...
        Slider({
         ...
          .onChange((value:number)=>{
            this.changeFontSize = value
            PreferencesUtil.saveChangeFontSize(this.changeFontSize)
          })
        ...
      }
    }
  }
}

3.获取保存的数据

数据都保存了,我们怎么去使用保存的数据呢?

import  PreferencesUtil  from '../common/database/PreferencesUtil'
import { ItemComponent } from '../view/ItemComponent'
import { SliderLayout } from '../view/SliderLayout'
import { TitleBarComponent } from '../view/TitleBarComponent'
import HomeViewModel from '../viewModel/HomeViewModel'
import SettingData from '../viewModel/SettingData'

@Entry
@Component
struct SetFontSizePage {
 ...
  @State changeFontSize: number = 0

  onPageShow(){
    PreferencesUtil.getChangeFontSize().then((value)=>{
      this.changeFontSize = value
    })
  }

}
import router from '@ohos.router'
import PreferencesUtil from '../common/database/PreferencesUtil'
import SettingItemComponent from '../view/SettingItemComponent'
import { TitleBarComponent } from '../view/TitleBarComponent'
import HomeViewModel from '../viewModel/HomeViewModel'
import SettingData from '../viewModel/SettingData'

@Entry
@Component
struct Index {
  ...
  @State changeFontSize: number = 16

  onPageShow(){
    PreferencesUtil.getChangeFontSize().then((value)=>{
      this.changeFontSize = value
    })
  }
  ...
}
...

效果图:
在这里插入图片描述

至此,大功告成~~~撒花

至此,所有功能已全部完成。

代码链接:https://gitee.com/runitwolf/set-app-font-size

typora笔记链接:https://gitee.com/runitwolf/set-app-font-size/blob/master/%E5%BA%94%E7%94%A8%E5%86%85%E5%AD%97%E4%BD%93%E5%A4%A7%E5%B0%8F%E8%B0%83%E8%8A%82.md

CSDN typora笔记链接 :https://download.csdn.net/download/qq_36067302/88671288


http://www.niftyadmin.cn/n/5301554.html

相关文章

提高工作效率的Postman环境变量使用方法

在 Postman 中&#xff0c;用 Environments 来管理环境变量。我们在开发的过程中&#xff0c;往往会用到多个环境&#xff1a;开发环境&#xff0c;测试环境&#xff0c;UAT 环境&#xff0c;生产环境等。我们要调用不同环境的 API 时&#xff0c;只需切换 Postman 的 Environm…

Linux学习(9)——RAID与服务器的常见故障

目录 一、服务器常见故障 1、系统不停重启进入不了系统 2、卡在开机界面右下角有fA B2 H8 3、系统安装不上 4、如何进入服务器的bios 5、一般进入阵列卡的快捷键 6.网络不通 7.硬盘不识别 二、RAID相关知识 1、RAID的概念 2、RAID功能实现 3、RAID实现的方式 三、…

轻松上手:Postman Interceptor 插件使用指南

什么是 Postman&#xff1f; Postman 是一种用于测试和开发 API 的工具&#xff0c;让开发者可以轻松地构建、发送、调试 HTTP 请求&#xff0c;并检查响应结果。通过Postman&#xff0c;开发者可以在不编写代码的情况下快速测试 API 的正确性和可靠性。Postman 还支持协作和自…

YApi怎么测试接口?简单实用教程

接口测试 为什么要接口测试&#xff1f; 你想想&#xff0c;你们后端团队写了几百个接口&#xff0c;兴高采烈地&#xff0c;直接部署上线&#xff0c;你们开开心心下班去。 等到晚上的时候&#xff0c;你发现你们的接口好几个都崩了&#xff0c;这导致了你们产品损失了一大…

Java 第19章 IO流 课堂练习+本章作业

文章目录 Buffered流拷贝二进制文件创建文件写入文本读取文本文件存读Properties文件 Buffered流拷贝二进制文件 package com.hspedu.chapter19.outputStream;import java.io.*;public class BufferedCopy02 {public static void main(String[] args) {String srcFilePath &q…

基于多反应堆的高并发服务器【C/C++/Reactor】(中)处理任务队列中的任务

一、处理任务队列中的任务 &#xff08;1&#xff09;EventLoop启动 EventLoop初始化和启动 // 启动反应堆模型 int eventLoopRun(struct EventLoop* evLoop) {assert(evLoop ! NULL);// 取出事件分发和检测模型struct Dispatcher* dispatcher evLoop->dispatcher;// 比较…

【Vue】响应式中的渲染 watcher

Vue 响应式 — 渲染 watcher 前三节内容&#xff1a; Vue 数据劫持 Vue 响应式初步 Vue 响应式中数组的特殊处理 在第二节中&#xff0c;我们简单了解了 watcher 类&#xff0c;当时我们说到&#xff0c;其一般用在渲染函数、计算属性以及侦听属性中&#xff0c;其一般用于…

内网环境安装python3版本,以及一些python的包

有一个flask服务现在已经在a服务器部署, 该服务要进行分布式部署,所以又申请了b,c,d三台服务器 现在要对这三台服务的python环境进行安装。 Linux服务器是内网的环境,服务器是内网相通的,abcd都不能连外网,但是有一台机器S和abcd相通也能连外网。 现在要做的事情就是把a服务器的…