HarmonyOS应用五之轻量化数据存储持久化

1、数据存储场景持久化方式

  • 用户首选项(Preferences):为应用提供Key-Value键值型的数据处理能力,通常用于保存应用的配置信息。数据通过文本的形式保存在设备中,应用使用过程中会将文本中的数据全量加载到内存中,所以访问速度快、效率高,但不适合需要存储大量数据的场景。
  • 关系型数据库(RelationalStore):一种关系型数据库,以行和列的形式存储数据,广泛用于应用中的关系型数据的处理,包括一系列的增、删、改、查等接口,开发者也可以运行自己定义的SQL语句来满足复杂业务场景的需要。
  • 键值型数据库(KV-Store):一种非关系型数据库,其数据以“键值”对的形式进行组织、索引和存储,其中“键”作为唯一标识符。适合很少数据关系和业务关系的业务数据存储,同时因其在分布式场景中降低了解决数据库版本兼容问题的复杂度,和数据同步过程中冲突解决的复杂度而被广泛使用。相比于关系型数据库,更容易做到跨设备跨版本兼容。

详细介绍以及使用流程

2、数据存储

/*
 * Copyright (c) 2022 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import { promptAction } from '@kit.ArkUI';
import { preferences } from '@kit.ArkData';
import Logger from '../common/utils/Logger';
import CommonConstants from '../common/constants/CommonConstants';
import Fruit from '../viewmodel/Fruit';

let context = getContext(this);
let preference: preferences.Preferences;
let preferenceTemp: preferences.Preferences;

/**
 * Preference model.
 *
 * @param fruitData Fruit data.
 */
class PreferenceModel {
  private fruitData: Fruit = new Fruit();

  /**
   * Read the specified Preferences persistence file and load the data into the Preferences instance.
   */
  async getPreferencesFromStorage() {
    try {
      preference = await preferences.getPreferences(context, CommonConstants.PREFERENCES_NAME);
    } catch (err) {
      Logger.error(CommonConstants.TAG, `Failed to get preferences, Cause: ${err}`);
    }
  }

  /**
   * Deletes the specified Preferences persistence file from memory and removes the Preferences instance.
   */
  async deletePreferences() {
    try {
      await preferences.deletePreferences(context, CommonConstants.PREFERENCES_NAME);
    } catch(err) {
      Logger.error(CommonConstants.TAG, `Failed to delete preferences, Cause: ${err}`);
    };
    preference = preferenceTemp;
    this.showToastMessage($r('app.string.delete_success_msg'));
  }

  /**
   * Save the data to the Preferences.
   *
   * @param fruit Fruit data.
   */
  async putPreference(fruit: Fruit) {
    if (!preference) {
      await this.getPreferencesFromStorage();
    }
    // The fruit name and fruit quantity data entered by the user are saved to the cached Preference instance.
    try {
      await preference.put(CommonConstants.KEY_NAME, JSON.stringify(fruit));
    } catch (err) {
      Logger.error(CommonConstants.TAG, `Failed to put value, Cause: ${err}`);
    }
    // Store the Preference instance in the preference persistence file
    await preference.flush();
  }

  /**
   * Get preference data.
   */
  async getPreference() {
    let fruit = '';
    if (!preference) {
      await this.getPreferencesFromStorage();
    }
    try {
      // fruit = <string> await preference.get(CommonConstants.KEY_NAME, '');
      fruit = (await preference.get(CommonConstants.KEY_NAME, '')).toString();
    } catch (err) {
      Logger.error(CommonConstants.TAG, `Failed to get value, Cause: ${err}`);
    }
    // If the data is empty, a message is displayed indicating that data needs to be written.
    if (fruit === '') {
      this.showToastMessage($r('app.string.data_is_null_msg'));
      return;
    }
    this.showToastMessage($r('app.string.read_success_msg'));
    return JSON.parse(fruit);
  }

  /**
   * Process the data obtained from the database.
   */
  async getFruitData() {
    this.fruitData = await this.getPreference();
    return this.fruitData;
  }

  /**
   * Verifies that the data entered is not empty.
   *
   * @param fruit Fruit data.
   */
  checkFruitData(fruit: Fruit) {
    if (fruit.fruitName === '' || fruit.fruitNum === '') {
      this.showToastMessage($r('app.string.fruit_input_null_msg'));
      return true;
    }
    return false;
  }

  /**
   * write data.
   *
   * @param fruit  Fruit data.
   */
  writeData(fruit: Fruit) {
    // Check whether the data is null.
    let isDataNull = this.checkFruitData(fruit);
    if (isDataNull) {
      return;
    }
    // The data is inserted into the preferences database if it is not empty.
    this.putPreference(fruit);
    this.showToastMessage($r('app.string.write_success_msg'));
  }

  /**
   * Popup window prompt message.
   *
   * @param message Prompt message.
   */
  showToastMessage(message: Resource) {
    promptAction.showToast({
      message: message,
      duration: CommonConstants.DURATION
    });
  };
}

export default new PreferenceModel();

数据存储调用代码:

 await preference.put(CommonConstants.KEY_NAME, JSON.stringify(fruit));

3、数据读取

 new ButtonItemData(
        $r('app.string.read_data_btn_text'),
        () => {
          // Get data from the preferences database.
          PreferenceModel.getFruitData().then((resultData: Fruit) => {
            if (resultData) {
              this.fruit = resultData;
            }
          });
        }
      ),
 async getFruitData() {
    this.fruitData = await this.getPreference();
    return this.fruitData;
  }
 async getPreference() {
    let fruit = '';
    if (!preference) {
      await this.getPreferencesFromStorage();
    }
    try {
      // fruit = <string> await preference.get(CommonConstants.KEY_NAME, '');
      fruit = (await preference.get(CommonConstants.KEY_NAME, '')).toString();
    } catch (err) {
      Logger.error(CommonConstants.TAG, `Failed to get value, Cause: ${err}`);
    }
    // If the data is empty, a message is displayed indicating that data needs to be written.
    if (fruit === '') {
      this.showToastMessage($r('app.string.data_is_null_msg'));
      return;
    }
    this.showToastMessage($r('app.string.read_success_msg'));
    return JSON.parse(fruit);
  }

根据debug流程发现请求如下:
PreferenceModel.getFruitData()-》await this.getPreference()(异步)-》await preference.get(CommonConstants.KEY_NAME, ‘’)).toString()(异步)-》然后原路返回PreferenceModel.getFruitData()走完-》this.showToastMessage(判断里面)-》getFruitData()
在这里插入图片描述
再执行完await preference.get(CommonConstants.KEY_NAME, ‘’)).toString()(异步)返回时走了then里面已经成功拿到数据了。

4、删除数据

 new ButtonItemData(
        $r('app.string.delete_data_file_btn_text'),
        () => {
          // Delete database files.
          PreferenceModel.deletePreferences();
          // After a database file is deleted, the corresponding data is left blank.
          this.fruit.fruitName = '';
          this.fruit.fruitNum = ''
        }
      )
  async deletePreferences() {
    try {
      await preferences.deletePreferences(context, CommonConstants.PREFERENCES_NAME);
    } catch(err) {
      Logger.error(CommonConstants.TAG, `Failed to delete preferences, Cause: ${err}`);
    };
    preference = preferenceTemp;
    this.showToastMessage($r('app.string.delete_success_msg'));
  }

await preferences.deletePreferences(context, CommonConstants.PREFERENCES_NAME);是根据实例名称删除指定的实例。

参考链接

5、应用内字体大小调节

  Slider({
            value: this.changeFontSize === CommonConstants.SET_SIZE_HUGE
              ? CommonConstants.SET_SLIDER_MAX : this.changeFontSize,
            min: CommonConstants.SET_SLIDER_MIN,
            max: CommonConstants.SET_SLIDER_MAX,
            step: CommonConstants.SET_SLIDER_STEP,
            style: SliderStyle.InSet
          })
            .showSteps(true)
            .width(StyleConstants.SLIDER_WIDTH_PERCENT)
            .onChange(async (value: number) => {
              if (this.changeFontSize === 0) {
                this.changeFontSize = await PreferencesUtil.getChangeFontSize();
                this.fontSizeText = SetViewModel.getTextByFontSize(value);
                return;
              }
              this.changeFontSize = (value === CommonConstants.SET_SLIDER_MAX ? CommonConstants.SET_SIZE_HUGE : value);
              this.fontSizeText = SetViewModel.getTextByFontSize(this.changeFontSize);
              PreferencesUtil.saveChangeFontSize(this.changeFontSize);
            })

在这里插入图片描述

滑动后触发onchange方法,value值监听到值大小,然后在首选项中保存更新字体大小值;保存后走Slider函数中替换新值并页面同步改变了字体大小。

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

bst@微胖子

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值