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函数中替换新值并页面同步改变了字体大小。