使用用戶首選項(xiàng)存儲(chǔ)、獲取、刪除數(shù)據(jù)—OpenHarmony數(shù)據(jù)管理
想了解更多關(guān)于開源的內(nèi)容,請(qǐng)?jiān)L問:
用戶首選項(xiàng)的基本能使用
場(chǎng)景說明
用戶首選項(xiàng)為應(yīng)用提供Key-Value鍵值型的數(shù)據(jù)處理能力,支持應(yīng)用持久化輕量級(jí)數(shù)據(jù),并對(duì)其修改和查詢。當(dāng)用戶希望有一個(gè)全局唯一存儲(chǔ)的地方,可以采用用戶首選項(xiàng)來進(jìn)行存儲(chǔ)。Preferences會(huì)將該數(shù)據(jù)緩存在內(nèi)存中,當(dāng)用戶讀取的時(shí)候,能夠快速?gòu)膬?nèi)存中獲取數(shù)據(jù)。Preferences會(huì)隨著存放的數(shù)據(jù)量越多而導(dǎo)致應(yīng)用占用的內(nèi)存越大,因此,Preferences不適合存放過多的數(shù)據(jù),適用的場(chǎng)景一般為應(yīng)用保存用戶的個(gè)性化設(shè)置(屏幕亮度,是否開啟夜間模式)等。
本例以一個(gè)小示例為大家介紹如何使用用戶首選項(xiàng)對(duì)數(shù)據(jù)進(jìn)行存儲(chǔ)、獲取、刪除。
效果呈現(xiàn)
本例最終效果如下:
使用用戶首選項(xiàng)存儲(chǔ)、獲取、刪除數(shù)據(jù)(OpenHarmony數(shù)據(jù)管理)-開源基礎(chǔ)軟件社區(qū)
運(yùn)行環(huán)境
本例基于以下環(huán)境開發(fā),開發(fā)者也可以基于其他適配的版本進(jìn)行開發(fā):
- IDE: DevEco Studio 4.0 Beta1
- SDK: Ohos_sdk_public 4.0.7.5 (API Version 10 Beta1)
實(shí)現(xiàn)思路
本例以設(shè)置屏幕亮度為例演示如何使用用戶首選項(xiàng)管理數(shù)據(jù),主要特性及實(shí)現(xiàn)方式如下:
- 當(dāng)用戶在文本框輸入數(shù)據(jù)后,點(diǎn)擊保存數(shù)據(jù),用戶首選項(xiàng)將數(shù)據(jù)緩存在內(nèi)存中:通過dataPreferences類的getPreferences方法獲取用戶首選項(xiàng)實(shí)例,然后通過該實(shí)例調(diào)用put方法將數(shù)據(jù)寫入內(nèi)存。
- 當(dāng)用戶點(diǎn)擊讀取數(shù)據(jù)時(shí),用戶首選項(xiàng)將數(shù)據(jù)從內(nèi)存中讀取出來并顯示在輸入框中:通過用戶首選項(xiàng)實(shí)例調(diào)用get方法獲取到保存的數(shù)據(jù),顯示在輸入框中。
- 當(dāng)用戶點(diǎn)擊刪除數(shù)據(jù)時(shí),用戶首選項(xiàng)將數(shù)據(jù)從內(nèi)存中刪除,用戶無法繼續(xù)讀取數(shù)據(jù):通過用戶首選項(xiàng)實(shí)例調(diào)用delete方法刪除保存的數(shù)據(jù)。
說明:
用戶首選項(xiàng)的使用需要注意以下幾點(diǎn):
- Key鍵為string類型,要求非空且長(zhǎng)度不超過80個(gè)字節(jié)。
- 如果Value值為string類型,請(qǐng)使用UTF-8編碼格式,可以為空,不為空時(shí)長(zhǎng)度不超過8192個(gè)字節(jié)。
- 內(nèi)存會(huì)隨著存儲(chǔ)數(shù)據(jù)量的增大而增大,所以存儲(chǔ)的數(shù)據(jù)量應(yīng)該是輕量級(jí)的,建議存儲(chǔ)的數(shù)據(jù)不超過一萬條,否則會(huì)在內(nèi)存方面產(chǎn)生較大的開銷。
開發(fā)步驟
由于本例重點(diǎn)講解用戶首選項(xiàng)的數(shù)據(jù)管理操作,所以開發(fā)步驟會(huì)著重講解如何通過用戶首選項(xiàng)完成數(shù)據(jù)的存儲(chǔ)、讀取和刪除,全量代碼可參考完整代碼章節(jié)。
首先自定義一個(gè)用戶首選項(xiàng)類,根據(jù)業(yè)務(wù)封裝相關(guān)方法方便后續(xù)調(diào)用。
其中包含數(shù)據(jù)處理的方法,用于完成數(shù)據(jù)的存儲(chǔ)、讀取和刪除操作。用戶首選項(xiàng)接口的使用方式主要在這部分呈現(xiàn),需要重點(diǎn)關(guān)注。
具體代碼如下:
import dataPreferences from '@ohos.data.preferences';
import promptAction from '@ohos.promptAction';
import ScreenBrightness from '../common/bean/Brightness';
let context = getContext(this);
let preference: dataPreferences.Preferences = null;
// 自定義用戶首選項(xiàng)類
class PreferenceModel {
private brightness:ScreenBrightness
// 創(chuàng)建用戶首選項(xiàng)實(shí)例preference
async getPreferencesFromStorage() {
try {
preference = await dataPreferences.getPreferences(context, 'setting.db');
} catch (err) {
Logger.error('[PreferenceModel]', `Failed to get preferences, Cause: ${err}`);
}
}
// 刪除數(shù)據(jù),調(diào)用dataPreferences的deletePreferences接口
async deletePreferences() {
try {
await dataPreferences.deletePreferences(context, 'setting.db');
} catch(err) {
Logger.error('[PreferenceModel]', `Failed to delete preferences, Cause: ${err}`);
};
preference = null;
this.showToastMessage($r('app.string.delete_success_msg'));
}
// 保存數(shù)據(jù)
async putPreference(screenBrightness:ScreenBrightness) {
if (preference === null) {
await this.getPreferencesFromStorage();
}
// 將用戶輸入的亮度數(shù)據(jù)保存到preference,調(diào)用用戶首選項(xiàng)實(shí)例的put接口
try {
await preference.put('screenBrightness', JSON.stringify(screenBrightness));
} catch (err) {
Logger.error('[PreferenceModel]', `Failed to put value, Cause: ${err}`);
}
// 使用flush方法將preferences實(shí)例的數(shù)據(jù)存儲(chǔ)到持久化文件,調(diào)用用戶首選項(xiàng)實(shí)例的flush接口
await preference.flush();
}
// 獲取數(shù)據(jù),調(diào)用用戶首選項(xiàng)實(shí)例的get接口
async getPreference() {
let screenBrightness = '';
if (preference === null) {
await this.getPreferencesFromStorage();
}
try {
screenBrightness = <string> await preference.get('screenBrightness', '');
} catch (err) {
Logger.error('[PreferenceModel]', `Failed to get value, Cause: ${err}`);
}
// 如果判斷數(shù)據(jù)為空則提示用戶先輸入數(shù)據(jù)
if (screenBrightness === '') {
this.showToastMessage($r('app.string.data_is_null_msg'));
return;
}
this.showToastMessage($r('app.string.read_success_msg'));
return JSON.parse(screenBrightness);
}
// 校驗(yàn)用戶輸入是否為空
checkData(screenBrightness:ScreenBrightness) {
if (screenBrightness.brightSwitch === '' || screenBrightness.defaultValue === '') {
this.showToastMessage($r('app.string.fruit_input_null_msg'));
return true;
}
return false;
}
// 點(diǎn)擊保存按鈕保存數(shù)據(jù)
writeData(screenBrightness:ScreenBrightness) {
// Check whether the data is null.
let isDataNull = this.checkData(screenBrightness);
if (isDataNull) {
return;
}
// The data is inserted into the preferences database if it is not empty.
this.putPreference(screenBrightness);
this.showToastMessage($r('app.string.write_success_msg'));
}
// 消息彈框
showToastMessage(message: Resource) {
promptAction.showToast({
message: message,
duration: 3000
});
};
}
UI中主要包含兩大部分:文本和輸入框,按鈕。將這兩部分分別抽取為子組件,在主頁中進(jìn)行調(diào)用。具體代碼如下:
文本和輸入框子組件:
import ScreenBrightness from '../common/bean/Brightness';
@Component
export default struct TextItemComponent {
private textResource: Resource;
private placeholderResource: Resource;
private marginBottom: string;
private marginTop: string;
private textInputType: InputType;
private textFlag: number;
@Link screenBrightness: ScreenBrightness;
private textInputCallBack: (value: string) => void;
aboutToAppear() {
if (this.textFlag === 0) {
this.marginTop = '8%';
this.marginBottom = '4%';
this.textInputType = InputType.Normal;
} else {
this.marginBottom = '321vp';
this.textInputType = InputType.Number;
}
}
build() {
Column() {
// 文本
Text(this.textResource)
.fontSize(25)
.height('3.2%')
.width('100%')
.fontColor("#182431")
.letterSpacing('1.58')
.fontWeight(500)
.margin({
bottom: '2%',
left: '7%',
top: this.marginTop
})
// 輸入框
TextInput({
placeholder: this.placeholderResource,
text: this.textFlag === 0 ? (this.screenBrightness.brightSwitch) : (this.screenBrightness.defaultValue)
})
.placeholderFont({ size: 20, weight: 500 })
.placeholderColor("#BDC1C4")
.caretColor(Color.Blue)
.type(this.textInputType)
.height('7%')
.width('93%')
.margin({ bottom: this.marginBottom })
.fontSize(20)
.fontColor("#182431")
.fontWeight(500)
.backgroundColor("#FFFFFF")
.onChange((value: string) => {
this.textInputCallBack(value);
})
}
}
}
按鈕子組件:
import PreferenceModel from '../model/PreferenceModel';
import ButtonItemData from '../common/bean/ButtonItemData';
import ScreenBrightness from '../common/bean/Brightness';
@Component
export default struct ButtonComponent {
private buttonItemValues: Array<ButtonItemData> = this.getButtonItemValues();
@Link screenBrightness: ScreenBrightness;
build() {
Column() {
ForEach(this.buttonItemValues, (item) => {
Button(item.text, { type: ButtonType.Capsule, stateEffect: true })
.backgroundColor("#E8A027")
.width('87%')
.height('6%')
.fontWeight(500)
.fontSize(20)
.margin({ bottom: '24vp' })
.onClick(() => {
item.clickMethod();
})
}, item => JSON.stringify(item))
}
}
// 在foreach中渲染Button組件時(shí)傳入不同按鈕的參數(shù)
getButtonItemValues() {
let values: Array<ButtonItemData> = [
new ButtonItemData(
'保存數(shù)據(jù)',
() => {
// 調(diào)用保存方法
PreferenceModel.writeData(this.screenBrightness);
}
),
new ButtonItemData(
'讀取數(shù)據(jù)',
() => {
// 調(diào)用讀取方法
PreferenceModel.getPreference().then(resultData => {
this.screenBrightness = resultData;
console.info('dbdata is '+JSON.stringify(resultData))
});
}
),
new ButtonItemData(
'刪除數(shù)據(jù)',
() => {
// 調(diào)用刪除方法
PreferenceModel.deletePreferences();
// 數(shù)據(jù)刪除后將相關(guān)內(nèi)容置為空
this.screenBrightness.brightSwitch = '';
this.screenBrightness.defaultValue = ''
}
)
];
return values;
}
}
構(gòu)建首頁UI。
在頁面生命周期的aboutToAppear中調(diào)用自定義首選項(xiàng)類的getPreference方法獲取到保存的數(shù)據(jù),這樣如果用戶之前有保存數(shù)據(jù)的話,進(jìn)入應(yīng)用中就可以顯示之前保存的數(shù)據(jù)。
具體代碼如下:
import PreferenceModel from '../model/PreferenceModel';
import ButtonComponent from '../view/ButtonComponent';
import TextItemComponent from '../view/TextItemComponent';
import ScreenBrightness from '../common/bean/Brightness';
@Entry
@Component
struct Setting {
@State screenBrightness: ScreenBrightness = new ScreenBrightness('', '');
build() {
Column() {
// 亮度調(diào)節(jié)文本及文本框
TextItemComponent({
textResource: $r('app.string.brightness_text'),
placeholderResource: $r('app.string.brightness_placeholder'),
textFlag: 0,
screenBrightness: $screenBrightness,
textInputCallBack: (value) => {
this.screenBrightness.brightSwitch = value;
}
})
// 設(shè)定值文本及文本框
TextItemComponent({
textResource: $r('app.string.defaultValue_text'),
placeholderResource: $r('app.string.defaultValue_placeholder'),
textFlag: 1,
screenBrightness: $screenBrightness,
textInputCallBack: (value) => {
this.screenBrightness.defaultValue = value;
}
})
// 按鈕
ButtonComponent({ screenBrightness: $screenBrightness })
}
.width('100%')
.height('100%')
.backgroundColor("#F1F3F5")
}
async aboutToAppear() {
await PreferenceModel.getPreferencesFromStorage();
// 獲取到之前保存的數(shù)據(jù),顯示在輸入框中
PreferenceModel.getPreference().then(resultData => {
this.screenBrightness = resultData;
});
}
}
完整代碼
由于開發(fā)步驟中已經(jīng)展示了大部分完整代碼,此處補(bǔ)充前文中未呈現(xiàn)的兩個(gè)數(shù)據(jù)類:
亮度數(shù)據(jù)類:
export default class ScreenBrightness {
// 亮度調(diào)節(jié)
brightSwitch: string;
// 設(shè)定值
defaultValue: string;
constructor(brightSwitch: string, defaultValue: string) {
this.brightSwitch = brightSwitch;
this.defaultValue = defaultValue;
}
}
按鈕數(shù)據(jù)類:
export default class ButtonItemData {
// 按鈕文本
text: string;
// 按鈕點(diǎn)擊事件觸發(fā)的方法
clickMethod: () => void;
constructor(text: string, clickMethod: () => void) {
this.text = text;
this.clickMethod = clickMethod;
}
}