概述
在移动互联网蓬勃发展的今天,移动应用给我们生活带来了极大的便利,这些便利的本质在于数据的互联互通。因此在应用的开发中数据存储占据了非常重要的位置,HarmonyOS应用开发也不例外。
本文将为您介绍HarmonyOS提供的数据管理能力之一首选项。
2 什么是首选项
首选项为应用提供Key-Value键值型的数据存储能力,支持应用持久化轻量级数据,并对其进行增删改查等。该存储对象中的数据会被缓存在内存中,因此它可以获得更快的存取速度,下面详细介绍下首选项的开发过程。
3 首选项运作机制
首选项的特点是:
1、以Key-Value形式存储数据
Key是不重复的关键字,Value是数据值。
2、非关系型数据库
区别于关系型数据库,它不保证遵循ACID(Atomicity, Consistency, Isolation and Durability)特性,数据之间无关系。
进程中每个文件仅存在一个Preferences实例,应用获取到实例后,可以从中读取数据,或者将数据存入实例中。通过调用flush方法可以将实例中的数据回写到文件里。
与关系数据库的区别
分类 | 关系型数据库 | 首选项 |
数据库类型 | 关系型 | 非关系型 |
使用场景 | 提供复杂场景下的本地数据库管理机制 | 对Key-Value结构的数据进行存取和持久化操作 |
存储方式 | SQLite数据库 | 文件 |
约束与限制 | 1.连接池最大4个 2.同一时间只支持一个写操作 | 1.建议数据不超一万条 2.Key为string型 |
4 常用接口介绍
常用接口有:保存数据(put)、获取数据(get)、是否包含指定的key(has)、删除数据(delete)、数据持久化(flush)等,后面依次详细介绍接口使用。
常用接口使用前提
1、需要导入@ohos.data.preferences模块到PreferencesUtil开发环境中,实例名字命名为dataPreferences,同时定义两个常量PREFERENCES_NAME和KEY_APP_FONT_SIZE。(注:把常用接口封装在PreferencesUtil工具类里面,为了方便后面代码直接调用)相关代码实现如下:
// PreferencesUtil.ets
import dataPreferences from '@ohos.data.preferences';
...
const PREFERENCES_NAME = 'myPreferences'; // 首选项名字
const KEY_APP_FONT_SIZE = 'appFontSize'; // 首选项Key字段
2、需要在entryAbility的onCreate方法获取首选项实例,以便后续能进行保存、读取、删除等操作,获取实例需要上下文context和文件名字PREFERENCES_NAME,相关代码实现如下:
// entryAbility.ets
onCreate(want, launchParam) {
Logger.info(TAG, 'onCreate');
globalThis.abilityWant = want;
// 创建首选项
PreferencesUtil.createFontPreferences(this.context);
...
}
// PreferencesUtil.ets
createFontPreferences(context) {
globalThis.getFontPreferences = (() => {
// 获取首选项实例
let preferences: Promise = dataPreferences.getPreferences(context, PREFERENCES_NAME);
return preferences;
});
}
保存数据(put)
1、在entryAbility的onCreate方法,调用PreferencesUtil.saveDefaultFontSize保存默认数据,先用has方法判断当前key是否有存在,如果没有就通过put方法把用户数据保存起来,该方法通过key-value键值对方式保存,常量KEY_APP_FONT_SIZE作为key,用户数据fontSize作为value,再通过flush方法把数据保存到文件,相关代码实现如下:
// entryAbility.ets
onCreate(want, launchParam) {
Logger.info(TAG, 'onCreate');
globalThis.abilityWant = want;
...
// 设置字体默认大小
PreferencesUtil.saveDefaultFontSize(Constants.SET_SIZE_STANDARD);
}
// PreferencesUtil.ets
saveDefaultFontSize(fontSize: number) {
globalThis.getFontPreferences().then((preferences) => {
// 判断保存的key是否存在
preferences.has(KEY_APP_FONT_SIZE).then(async (isExist) => {
Logger.info(TAG, 'preferences has changeFontSize is ' + isExist);
if (!isExist) {
// 保存数据
await preferences.put(KEY_APP_FONT_SIZE, fontSize);
preferences.flush();
}
}).catch((err) => {
Logger.error(TAG, 'Has the value failed with err: ' + err);
});
}).catch((err) => {
Logger.error(TAG, 'Get the preferences failed, err: ' + err);
});
}
2、在SetFontSizePage页面,当手指移动Slider滑动条时,在onChange方法回调当前进度值,把当前进度值通过PreferencesUtil.saveChangeFontSize方法保存起来,再通过flush方法把数据保存到文件,相关代码实现如下:
// SetFontSizePage.ets
build() {
Row() {
Slider({
...
}).onChange((value: number) => {
// 保存当前进度值
PreferencesUtil.saveChangeFontSize(this.changeFontSize);
})
}
}
// PreferencesUtil.ets
saveChangeFontSize(fontSize: number) {
globalThis.getFontPreferences().then(async (preferences) => {
// 保存数据
await preferences.put(KEY_APP_FONT_SIZE, fontSize);
preferences.flush();
}).catch((err) => {
Logger.error(TAG, 'put the preferences failed, err: ' + err);
});
}
获取数据(get)
在HomePage的onPageShow方法,调用PreferencesUtil.getChangeFontSize方法获取用户数据,调用get方法获取,该方法通过key-value键值对方式读取,常量KEY_APP_FONT_SIZE作为key,默认数据fontSize作为value,把的到的结果赋值给变量fontSize,通过return方式把值返回去,相关代码实现如下:
// HomePage.ets
onPageShow() {
PreferencesUtil.getChangeFontSize().then((value) => {
this.changeFontSize = value;
Logger.info(TAG, 'Get the value of changeFontSize: ' + this.changeFontSize);
});
}
// PreferencesUtil.ets
async getChangeFontSize() {
let fontSize: number = 0;
const preferences = await globalThis.getFontPreferences();
fontSize = await preferences.get(KEY_APP_FONT_SIZE, fontSize);
return fontSize;
}
是否包含指定的key(has)
通过has方法判断首选项中是否包含指定的key,保证指定的key不会被重复保存,相关代码实现如下:
// PreferencesUtil.ets
saveDefaultFontSize(fontSize: number) {
globalThis.getFontPreferences().then((preferences) => {
// 判断保存的key是否存在
preferences.has(KEY_APP_FONT_SIZE).then(async (isExist) => {
Logger.info(TAG, 'preferences has changeFontSize is ' + isExist);
}).catch((err) => {
Logger.error(TAG, 'Has the value failed with err: ' + err);
});
}).catch((err) => {
Logger.error(TAG, 'Get the preferences failed, err: ' + err);
});
}
数据持久化(flush)
通过flush方法把应用数据保存到文件中,使得应用数据保存期限变长,相关代码实现如下:
// PreferencesUtil.ets
saveChangeFontSize(fontSize: number) {
globalThis.getFontPreferences().then(async (preferences) => {
// 保存数据
await preferences.put(KEY_APP_FONT_SIZE, fontSize);
// 数据持久化
preferences.flush();
}).catch((err) => {
Logger.error(TAG, 'put the preferences failed, err: ' + err);
});
}
删除数据(delete)
删除首选项数据需要获取preferences实例,用delete方法删除指定的key所对应的值,常量KEY_APP_FONT_SIZE作为key,通过Promise异步回调是否删除成功,相关代码实现如下:
// PreferencesUtil.ets
async deleteChangeFontSize() {
const preferences: dataPreferences.Preferences = await globalThis.getFontPreferences();
// 删除数据
let deleteValue = preferences.delete(KEY_APP_FONT_SIZE);
deleteValue.then(() => {
Logger.info(TAG, 'Succeeded in deleting the key appFontSize.');
}).catch((err) => {
Logger.error(TAG, 'Failed to delete the key appFontSize. Cause: ' + err);
});
}
5 参考链接
- 首选项参考:首选项。 案例:应用内字体大小调节
介绍
本篇Codelab将介绍如何使用基础组件Slider,通过拖动滑块调节应用内字体大小。要求完成以下功能:
- 实现两个页面的UX:主页面和字体大小调节页面。
- 拖动滑块改变字体大小系数,列表页和调节页面字体大小同步变化。往右拖动滑块字体变大,反之变小。
- 字体大小支持持久化存储,再次启动时,应用内字体仍是调节后的字体大小。
最终效果图如图所示:
相关概念
- 字体大小调节原理:通过组件Slider滑动,获取滑动数值,将这个值通过首选项进行持久化,页面的字体通过这个值去改变大小。
- 首选项:首选项为应用提供Key-Value键值型的数据处理能力,支持应用持久化轻量级数据,并对其修改和查询。
完整实例
gitee源码地址
源码下载
应用内字体大小调节(ArkTS).zip
环境搭建
我们首先需要完成HarmonyOS开发环境搭建,可参照如下步骤进行。
软件要求
- DevEco Studio版本:DevEco Studio 3.1 Release。
- HarmonyOS SDK版本:API version 9。
硬件要求
- 设备类型:华为手机或运行在DevEco Studio上的华为手机设备模拟器。
- HarmonyOS系统:3.1.0 Developer Release。
环境搭建
- 安装DevEco Studio,详情请参考下载和安装软件。
- 设置DevEco Studio开发环境,DevEco Studio开发环境需要依赖于网络环境,需要连接上网络才能确保工具的正常使用,可以根据如下两种情况来配置开发环境:
- 如果可以直接访问Internet,只需进行下载HarmonyOS SDK操作。
- 如果网络不能直接访问Internet,需要通过代理服务器才可以访问,请参考配置开发环境。
- 开发者可以参考以下链接,完成设备调试的相关配置:
- 使用真机进行调试
- 使用模拟器进行调试
代码结构解读
本篇Codelab只对核心代码进行讲解,对于完整代码,我们会在源码下载或gitee中提供。
No Preview
- ├──entry/src/main/ets // ArkTS代码区
- │ ├──common
- │ │ ├──constants
- │ │ │ ├──CommonConstants.ets // 公共常量类
- │ │ │ └──StyleConstants.ets // 属性常量类
- │ │ ├──database
- │ │ │ └──PreferencesUtil.ets // 首选项数据操作工具类
- │ │ └──utils
- │ │ ├──GlobalContext.ets // 全局上下文工具类
- │ │ └──Logger.ets // 日志工具类
- │ ├──entryability
- │ │ └──EntryAbility.ets // 程序入口类
- │ ├──pages
- │ │ ├──HomePage.ets // 主页面
- │ │ └──SetFontSizePage.ets // 字体大小调节页面
- │ ├──view
- │ │ ├──ChatItemComponent.ets // 字体大小调节页面聊天Item组件
- │ │ ├──SettingItemComponent.ets // 主页面列表Item组件
- │ │ └──TitleBarComponent.ets // 页面标题栏组件
- │ └──viewmodel
- │ ├──ChatData.ets // 聊天列表数据类
- │ ├──HomeViewModel.ets // 主页面数据模型
- │ ├──ItemDirection.ets // 聊天数据位置
- │ └──SettingData.ets // 设置列表数据类
- │ └──SetViewModel.ets // 字体大小调节页面数据模型
- └──entry/src/main/resources // 资源文件目录
保存默认大小
应用初始化时,为了保证页面中文本的正常显示。在entryAbility生命周期onCreate方法处,添加一个命名为“myPreferences”的首选项表。在表中添加一个名为“appFontSize”的字段,保存默认字体大小。
No Preview
// PreferencesUtil.ets
// 导入首选项数据库
import dataPreferences from '@ohos.data.preferences';
export class PreferencesUtil {
// 先将Promise<Preferences>保存到全局
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);
});
}
}
获取字体大小
在HomePage页面加载显示的时候,即生命周期onPageShow方法处,通过PreferencesUtil工具类中的getChangeFontSize方法读取首选项中的数据。
将读取到的数据保存到页面带有@State的变量中,通过这个变量对文本字体大小进行设置。
No Preview
// HomePage.ets
onPageShow() {
PreferencesUtil.getChangeFontSize().then((value) => {
this.changeFontSize = value;
Logger.info(TAG, 'Get the value of changeFontSize: ' + this.changeFontSize);
})
}
// PreferencesUtil.ets工具类
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;
}
修改字体大小
在应用主页面,点击设置字体大小,可以跳转到字体大小调节页面。拖动滑块修改数据后,SetFontSizePage页面的Slider组件监听到onChange事件,改变字体大小后,调用PreferencesUtil工具类中saveChangeFontSize方法写入本条数据即可。
No Preview
// SetFontSizePage.ets
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
})
...
.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);
})
// PreferencesUtil.ets工具类
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);
});
}
总结
您已经完成了本次Codelab的学习,并了解到以下知识点:
- 使用Slider实现滑动条。
- 使用首选项实现持久化应用轻量级数据。