我想给别人做网站,企业只有建立自己的网站平台,搜索排名广告营销,网页设计培训有工资吗在应用开发中存储一些配置是很常见的需求。在android中有SharedPreferences#xff0c;一个轻量级的存储类#xff0c;用来保存应用的一些常用配置。在HarmonyOS鸿蒙应用开发中#xff0c;实现类似功能的也叫首选项#xff0c;dataPreferences。 相关概念
ohos.data.prefe… 在应用开发中存储一些配置是很常见的需求。在android中有SharedPreferences一个轻量级的存储类用来保存应用的一些常用配置。在HarmonyOS鸿蒙应用开发中实现类似功能的也叫首选项dataPreferences。 相关概念
ohos.data.preferences (用户首选项)
dataPreferences首选项为应用提供Key-Value键值型的数据处理能力支持应用持久化轻量级数据并对其修改和查询。数据存储形式为键值对键的类型为字符串型值的存储数据类型包括数字型、字符型、布尔型以及这3种类型的数组类型。
如何使用
导入模块
import dataPreferences from ohos.data.preferences;
常量 系统能力 SystemCapability.DistributedDataManager.Preferences.Core 名称 参数类型 可读 可写 说明 MAX_KEY_LENGTH number 是 否 Key的最大长度限制为80个字节。 MAX_VALUE_LENGTH number 是 否 Value的最大长度限制为8192个字节。
dataPreferences.getPreferences getPreferences(context: Context, name: string, callback: AsyncCallbackPreferences): void
获取Preferences实例使用callback异步回调。
系统能力 SystemCapability.DistributedDataManager.Preferences.Core
Stage模型使用示例
import UIAbility from ohos.app.ability.UIAbility;let preferences null;class EntryAbility extends UIAbility {onWindowStageCreate(windowStage) {try {dataPreferences.getPreferences(this.context, mystore, function (err, val) {if (err) {console.error(Failed to get preferences. code err.code , message err.message);return;}preferences val;console.info(Succeeded in getting preferences.);})} catch (err) {console.error(Failed to get preferences. code err.code , message err.message);}}
}
首选项使用demo
软件要求
DevEco Studio版本DevEco Studio 3.1 Release。HarmonyOS SDK版本API version 9。 代码结构
├──entry/src/main/ets // 代码区
│ ├──common
│ │ ├──constants
│ │ │ ├──CommonConstants.ets // 公共常量类
│ │ │ └──StyleConstants.ets // 样式常量类
│ │ └──utils
│ │ └──Logger.ets // 日志打印类
│ ├──entryability
│ │ └──EntryAbility.ts // 程序入口类
│ ├──model
│ │ └──PreferenceModel.ets // 首选项相关方法类
│ ├──pages
│ │ └──Index.ets // 主界面
│ ├──view
│ │ ├──ButtonComponent.ets // 自定义Button组件类
│ │ └──TextItemComponent.ets // 自定义Text组件类
│ └──viewmodel
│ ├──ButtonItemData.ets // 按钮数据类
│ └──Fruit.ets // 水果数据类
└──entry/src/main/resources // 资源文件目录
构建主界面
在这个任务中我们将完成示例主界面的开发效果如图所示 从上面效果图可以看出主界面主要由2个相同样式的文本和文本输入框以及3个相同样式的按钮组成。我们可以将文本和文本输入框抽取成一个TextItemComponent子组件。再将按钮抽取成一个ButtonComponent子组件。
在ets目录下点击鼠标右键 New Directory新建名为view的自定义子组件目录。然后在view目录下点击鼠标右键 New ArkTS File新建两个ArkTS文件分别为TextItemComponent子组件、ButtonComponent子组件。可以看到文件目录结构效果如图所示 // TextItemComponent.ets
Component
export default struct TextItemComponent {private textResource: Resource $r(app.string.empty); // 按钮文本资源private placeholderResource: Resource $r(app.string.empty); // placeholder文本资源private marginBottom: string ;private marginTop: string ;private textInputType: InputType InputType.Normal; // 输入框输入数据类型private textFlag: number 0; // 文本框标记Link fruit: Fruit; // 水果数据private textInputCallBack (value: string) {}; // TextInput的回调build() {Column() {Text(this.textResource).fontSize(StyleConstants.TEXT_FONT_SIZE).height(StyleConstants.TEXT_HEIGHT).width(StyleConstants.FULL_PERCENT).fontColor($r(app.color.text_font_color)).letterSpacing(StyleConstants.LETTER_SPACING).fontWeight(StyleConstants.FONT_WEIGHT).margin({bottom: StyleConstants.TEXT_MARGIN_BOTTOM,left: StyleConstants.TEXT_MARGIN_LEFT,top: this.marginTop})TextInput({placeholder: this.placeholderResource,text: this.textFlag 0 ? (this.fruit.fruitName) : (this.fruit.fruitNum)}).placeholderFont({ size: StyleConstants.FONT_SIZE, weight: StyleConstants.FONT_WEIGHT }).placeholderColor($r(app.color.placeholder_color)).caretColor(Color.Blue).type(this.textInputType).height(StyleConstants.TEXT_INPUT_HEIGHT).width(StyleConstants.TEXT_INPUT_WIDTH).margin({ bottom: this.marginBottom }).fontSize(StyleConstants.FONT_SIZE).fontColor($r(app.color.text_font_color)).fontWeight(StyleConstants.FONT_WEIGHT).backgroundColor($r(app.color.white)).onChange((value: string) {this.textInputCallBack(value);})}}
}
// ButtonComponent.ets
Component
export default struct ButtonComponent {private buttonItemValues: ArrayButtonItemData this.getButtonItemValues();Link fruit: Fruit; // 水果数据 build() {Column() {ForEach(this.buttonItemValues, (item: ButtonItemData) {Button(item.resource, { type: ButtonType.Capsule, stateEffect: true }).backgroundColor($r(app.color.button_background_color)).width(StyleConstants.BUTTON_WIDTH).height(StyleConstants.BUTTON_HEIGHT).fontWeight(StyleConstants.FONT_WEIGHT).fontSize(StyleConstants.FONT_SIZE).margin({ bottom: StyleConstants.BUTTON_MARGIN_BOTTOM }).onClick(() {item.clickMethod();})}, (item: ButtonItemData) JSON.stringify(item))}}
}
在Index.ets主界面中引用TextItemComponent和ButtonComponent子组件。
// Index.ets
Column() {// 水果名称输入框TextItemComponent({textResource: $r(app.string.fruit_text),placeholderResource: $r(app.string.fruit_placeholder),textFlag: CommonConstants.FRUIT_FLAG,fruit: $fruit,textInputCallBack: (value: string) {this.fruit.fruitName value;}})// 水果数量输入框TextItemComponent({textResource: $r(app.string.number_text),placeholderResource: $r(app.string.number_placeholder),textFlag: CommonConstants.NUMBER_FLAG,fruit: $fruit,textInputCallBack: (value: string) {this.fruit.fruitNum value;}})// 按钮组件ButtonComponent({ fruit: $fruit })
}
.width(StyleConstants.FULL_PERCENT)
.height(StyleConstants.FULL_PERCENT)
.backgroundColor($r(app.color.main_background_color))
创建数据文件
创建数据文件需要如下两个步骤 导入dataPreferences模块。 通过dataPreferences模块的getPreferences(context, name)方法获取到对应文件名的Preferences实例。
Preferences的数据存储在文件中因此需要指定存储的文件名PREFERENCES_NAME。再通过Preferences提供的方法进行数据库的相关操作。
// PreferenceModel.ets
// 导入dataPreferences模块
import dataPreferences from ohos.data.preferences;let context getContext(this);
let preference: dataPreferences.Preferences;
let preferenceTemp: dataPreferences.Preferences;// 调用getPreferences方法读取指定首选项持久化文件将数据加载到Preferences实例用于数据操作
async getPreferencesFromStorage() {try {preference await dataPreferences.getPreferences(context, CommonConstants.PREFERENCES_NAME);} catch (err) {Logger.error(CommonConstants.TAG, Failed to get preferences, Cause: ${err});}
}
写入数据
获取Preferences实例后使用Preferences的put方法将用户输入的水果名称和水果数量数据保存到缓存的实例中。再通过Preferences的flush方法将Preferences实例异步存储到首选项持久化文件中。
// PreferenceModel.ets
async putPreference(fruit: Fruit) {...try {// 将用户输入的水果名称和水果数量数据保存到缓存的Preference实例中await preference.put(CommonConstants.KEY_NAME, JSON.stringify(fruit));} catch (err) {Logger.error(CommonConstants.TAG, Failed to put value, Cause: ${err});}// 将Preference实例存储到首选项持久化文件中await preference.flush();
}
读取数据
使用Preferences的get方法读取数据。如果键不存在则返回默认值。例如获取下面代码中fruit的值如果fruit的键KEY_NAME不存在则会返回空字符串。通过默认值的设置来避免程序出现异常。
// PreferenceModel.ets
async getPreference() {let fruit ;...try {fruit (await preference.get(CommonConstants.KEY_NAME, )).toString();} catch (err) {Logger.error(CommonConstants.TAG, Failed to get value, Cause: ${err});}
}
删除数据文件
通过dataPreferences模块的deletePreferences(context, name)方法从内存中移除指定文件对应的Preferences单实例。移除Preferences单实例时应用不允许再使用该实例进行数据操作否则会出现数据一致性问题。
// PreferenceModel.ets
async deletePreferences() {try {await dataPreferences.deletePreferences(context, CommonConstants.PREFERENCES_NAME);} catch(err) {Logger.error(CommonConstants.TAG, Failed to delete preferences, Cause: ${err});}...
}
附上demo源码地址demo源码
注意和AppStorage区别
AppStorage是应用全局的UI状态存储是和应用的进程绑定的由UI框架在应用程序启动时创建为应用程序UI状态属性提供中央存储。
和AppStorage不同的是LocalStorage是页面级的通常应用于页面内的数据共享。而AppStorage是应用级的全局状态共享还相当于整个应用的“中枢”持久化数据PersistentStorage和环境变量Environment都是通过和AppStorage中转才可以和UI交互。
AppStorage
AppStorage是在应用启动的时候会被创建的单例。它的目的是为了提供应用状态数据的中心存储这些状态数据在应用级别都是可访问的。AppStorage将在应用运行过程保留其属性。属性通过唯一的键字符串值访问。
AppStorage可以和UI组件同步且可以在应用业务逻辑中被访问。
AppStorage中的属性可以被双向同步数据可以是存在于本地或远程设备上并具有不同的功能比如数据持久化详见PersistentStorage。这些数据是通过业务逻辑中实现与UI解耦如果希望这些数据在UI中使用需要用到StorageProp和StorageLink。
由于AppStorage是内存内数据该行为会导致数据丧失持久化能力。
StorageProp
在上文中已经提到如果要建立AppStorage和自定义组件的联系需要使用StorageProp和StorageLink装饰器。使用StorageProp(key)/StorageLink(key)装饰组件内的变量key标识了AppStorage的属性。
当自定义组件初始化的时候StorageProp(key)/StorageLink(key)装饰的变量会通过给定的key绑定在AppStorage对应的属性完成初始化。本地初始化是必要的因为无法保证AppStorage一定存在给定的key这取决于应用逻辑是否在组件初始化之前在AppStorage实例中存入对应的属性。
StorageProp(key)是和AppStorage中key对应的属性建立单向数据同步我们允许本地改变的发生但是对于StorageProp本地的修改永远不会同步回AppStorage中相反如果AppStorage给定key的属性发生改变改变会被同步给StorageProp并覆盖掉本地的修改。
PersistentStorage
最后需要注意的是LocalStorage和AppStorage都是运行时的内存但是在应用退出再次启动后依然能保存选定的结果需要用到PersistentStorage。
PersistentStorage是应用程序中的可选单例对象。此对象的作用是持久化存储选定的AppStorage属性以确保这些属性在应用程序重新启动时的值与应用程序关闭时的值相同。虽然借助PersistentStorage也可以实现数据的持久话但它是用来持久化UI状态的注意和用户首选项的区别如果是一些配置存储使用用户首选项。
综上所述什么时候用PersistentStorage在应用退出再次启动后依然能保存选定的结果是应用开发中十分常见的现象这就需要用到PersistentStorage。
限制条件
PersistentStorage允许的类型和值有
number, string, boolean, enum 等简单类型。可以被JSON.stringify()和JSON.parse()重构的对象。例如Date, Map, Set等内置类型则不支持以及对象的属性方法不支持持久化。
PersistentStorage不允许的类型和值有
不支持嵌套对象对象数组对象的属性是对象等。因为目前框架无法检测AppStorage中嵌套对象包括数组值的变化所以无法写回到PersistentStorage中。不支持undefined 和 null 。
持久化数据是一个相对缓慢的操作应用程序应避免以下情况
持久化大型数据集。持久化经常变化的变量。
PersistentStorage的持久化变量最好是小于2kb的数据不要大量的数据持久化因为PersistentStorage写入磁盘的操作是同步的大量的数据本地化读写会同步在UI线程中执行影响UI渲染性能。如果开发者需要存储大量的数据建议使用数据库api。
PersistentStorage只能在UI页面内使用否则将无法持久化数据。
PersistentStorage将选定的AppStorage属性保留在设备磁盘上。应用程序通过API以决定哪些AppStorage属性应借助PersistentStorage持久化。UI和业务逻辑不直接访问PersistentStorage中的属性所有属性访问都是对AppStorage的访问AppStorage中的更改会自动同步到PersistentStorage。
PersistentStorage和AppStorage中的属性建立双向同步。应用开发通常通过AppStorage访问PersistentStorage另外还有一些接口可以用于管理持久化属性但是业务逻辑始终是通过AppStorage获取和设置属性的。
更多介绍参见官方文档PersistentStorage持久化存储UI状态
其他资源
ohos.data.preferences (用户首选项)
文档中心--Codelabs
AppStorage应用全局的UI状态存储
健康生活应用ArkTS_华为开发者HarmonyOS专区小助手-华为开发者联盟HarmonyOS专区
harmonyOS鸿蒙-数据管理-用户首选项(ohos.data.preferences)_harmonyos datapreferences-CSDN博客
HarmonyOS-AppStorage应用全局的UI状态存储-CSDN博客
HarmonyOS 网络请求以及数据持久化-CSDN博客
https://developer.huawei.com/consumer/cn/codelabsPortal/carddetails/tutorials_HarmonyOS-HealthyLife
https://developer.huawei.com/consumer/cn/codelabsPortal/carddetails/tutorials_Preferences
HarmonyOS应用开发-首选项与后台通知管理_ohos.data.preferences-CSDN博客