1# 用户首选项的基本使用 2 3## 场景说明 4用户首选项为应用提供Key-Value键值型的数据处理能力,支持应用持久化轻量级数据,并对其修改和查询。当用户希望有一个全局唯一存储的地方,可以采用用户首选项来进行存储。用户首选项会将该数据缓存在内存中,当用户读取的时候,能够快速从内存中获取数据。用户首选项会随着存放的数据量越多而导致应用占用的内存越大,因此,用户首选项不适合存放过多的数据,适用的场景一般为应用保存用户的个性化设置(屏幕亮度,是否开启夜间模式)等。 5本例以一个小示例为大家介绍如何使用用户首选项对数据进行存储、获取、删除。 6 7## 效果呈现 8本例最终效果如下: 9 10 11 12## 运行环境 13本例基于以下环境开发,开发者也可以基于其他适配的版本进行开发: 14 15- IDE: DevEco Studio 4.0 Beta1 16- SDK: Ohos_sdk_public 4.0.7.5 (API Version 10 Beta1) 17 18## 实现思路 19本例以设置屏幕亮度为例演示如何使用用户首选项管理数据,主要特性及实现方式如下: 20- 当用户在文本框输入数据后,点击保存数据,用户首选项将数据缓存在内存中:通过dataPreferences类的getPreferences方法获取用户首选项实例,然后通过该实例调用put方法将数据写入内存。 21- 当用户点击读取数据时,用户首选项将数据从内存中读取出来并显示在输入框中:通过用户首选项实例调用get方法获取到保存的数据,显示在输入框中。 22- 当用户点击删除数据时,用户首选项将数据从内存中删除,用户无法继续读取数据:通过用户首选项实例调用delete方法删除保存的数据。 23 24>  **说明:** 25> 用户首选项的使用需要注意以下几点: 26> - Key键为string类型,要求非空且长度不超过80个字节。 27> - 如果Value值为string类型,请使用UTF-8编码格式,可以为空,不为空时长度不超过8192个字节。 28> - 内存会随着存储数据量的增大而增大,所以存储的数据量应该是轻量级的,建议存储的数据不超过一万条,否则会在内存方面产生较大的开销。 29 30## 开发步骤 31由于本例重点讲解用户首选项的数据管理操作,所以开发步骤会着重讲解如何通过用户首选项完成数据的存储、读取和删除,全量代码可参考完整代码章节。 321. 首先自定义一个用户首选项类,根据业务封装相关方法方便后续调用。 33 其中包含数据处理的方法,用于完成数据的存储、读取和删除操作。用户首选项接口的使用方式主要在这部分呈现,需要重点关注。 34 具体代码如下: 35 ```ts 36 import dataPreferences from '@ohos.data.preferences'; 37 import promptAction from '@ohos.promptAction'; 38 import ScreenBrightness from '../common/bean/Brightness'; 39 40 let context = getContext(this); 41 let preference: dataPreferences.Preferences = null; 42 43 // 自定义用户首选项类 44 class PreferenceModel { 45 private brightness:ScreenBrightness 46 47 // 创建用户首选项实例preference 48 async getPreferencesFromStorage() { 49 try { 50 preference = await dataPreferences.getPreferences(context, 'setting.db'); 51 } catch (err) { 52 Logger.error('[PreferenceModel]', `Failed to get preferences, Cause: ${err}`); 53 } 54 } 55 56 // 删除数据,调用dataPreferences的deletePreferences接口 57 async deletePreferences() { 58 try { 59 await dataPreferences.deletePreferences(context, 'setting.db'); 60 } catch(err) { 61 Logger.error('[PreferenceModel]', `Failed to delete preferences, Cause: ${err}`); 62 }; 63 preference = null; 64 this.showToastMessage($r('app.string.delete_success_msg')); 65 } 66 67 // 保存数据 68 async putPreference(screenBrightness:ScreenBrightness) { 69 if (preference === null) { 70 await this.getPreferencesFromStorage(); 71 } 72 // 将用户输入的亮度数据保存到preference,调用用户首选项实例的put接口 73 try { 74 await preference.put('screenBrightness', JSON.stringify(screenBrightness)); 75 } catch (err) { 76 Logger.error('[PreferenceModel]', `Failed to put value, Cause: ${err}`); 77 } 78 // 使用flush方法将preferences实例的数据存储到持久化文件,调用用户首选项实例的flush接口 79 await preference.flush(); 80 } 81 82 // 获取数据,调用用户首选项实例的get接口 83 async getPreference() { 84 let screenBrightness = ''; 85 if (preference === null) { 86 await this.getPreferencesFromStorage(); 87 } 88 try { 89 screenBrightness = <string> await preference.get('screenBrightness', ''); 90 } catch (err) { 91 Logger.error('[PreferenceModel]', `Failed to get value, Cause: ${err}`); 92 } 93 // 如果判断数据为空则提示用户先输入数据 94 if (screenBrightness === '') { 95 this.showToastMessage($r('app.string.data_is_null_msg')); 96 return; 97 } 98 this.showToastMessage($r('app.string.read_success_msg')); 99 return JSON.parse(screenBrightness); 100 } 101 102 // 校验用户输入是否为空 103 checkData(screenBrightness:ScreenBrightness) { 104 if (screenBrightness.brightSwitch === '' || screenBrightness.defaultValue === '') { 105 this.showToastMessage($r('app.string.fruit_input_null_msg')); 106 return true; 107 } 108 return false; 109 } 110 111 // 点击保存按钮保存数据 112 writeData(screenBrightness:ScreenBrightness) { 113 // Check whether the data is null. 114 let isDataNull = this.checkData(screenBrightness); 115 if (isDataNull) { 116 return; 117 } 118 // The data is inserted into the preferences database if it is not empty. 119 this.putPreference(screenBrightness); 120 this.showToastMessage($r('app.string.write_success_msg')); 121 } 122 123 // 消息弹框 124 showToastMessage(message: Resource) { 125 promptAction.showToast({ 126 message: message, 127 duration: 3000 128 }); 129 }; 130 } 131 export default new PreferenceModel(); 132 ``` 1332. UI中主要包含两大部分:文本和输入框,按钮。将这两部分分别抽取为子组件,在主页中进行调用。具体代码如下: 134 文本和输入框子组件: 135 ```ts 136 import ScreenBrightness from '../common/bean/Brightness'; 137 138 @Component 139 export default struct TextItemComponent { 140 private textResource: Resource; 141 private placeholderResource: Resource; 142 private marginBottom: string; 143 private marginTop: string; 144 private textInputType: InputType; 145 private textFlag: number; 146 @Link screenBrightness: ScreenBrightness; 147 private textInputCallBack: (value: string) => void; 148 149 aboutToAppear() { 150 if (this.textFlag === 0) { 151 this.marginTop = '8%'; 152 this.marginBottom = '4%'; 153 this.textInputType = InputType.Normal; 154 } else { 155 this.marginBottom = '321vp'; 156 this.textInputType = InputType.Number; 157 } 158 } 159 160 build() { 161 Column() { 162 // 文本 163 Text(this.textResource) 164 .fontSize(25) 165 .height('3.2%') 166 .width('100%') 167 .fontColor("#182431") 168 .letterSpacing('1.58') 169 .fontWeight(500) 170 .margin({ 171 bottom: '2%', 172 left: '7%', 173 top: this.marginTop 174 }) 175 // 输入框 176 TextInput({ 177 placeholder: this.placeholderResource, 178 text: this.textFlag === 0 ? (this.screenBrightness.brightSwitch) : (this.screenBrightness.defaultValue) 179 }) 180 .placeholderFont({ size: 20, weight: 500 }) 181 .placeholderColor("#BDC1C4") 182 .caretColor(Color.Blue) 183 .type(this.textInputType) 184 .height('7%') 185 .width('93%') 186 .margin({ bottom: this.marginBottom }) 187 .fontSize(20) 188 .fontColor("#182431") 189 .fontWeight(500) 190 .backgroundColor("#FFFFFF") 191 .onChange((value: string) => { 192 this.textInputCallBack(value); 193 }) 194 } 195 } 196 } 197 ``` 198 按钮子组件: 199 ```ts 200 import PreferenceModel from '../model/PreferenceModel'; 201 import ButtonItemData from '../common/bean/ButtonItemData'; 202 import ScreenBrightness from '../common/bean/Brightness'; 203 204 @Component 205 export default struct ButtonComponent { 206 private buttonItemValues: Array<ButtonItemData> = this.getButtonItemValues(); 207 @Link screenBrightness: ScreenBrightness; 208 209 build() { 210 Column() { 211 ForEach(this.buttonItemValues, (item) => { 212 Button(item.text, { type: ButtonType.Capsule, stateEffect: true }) 213 .backgroundColor("#E8A027") 214 .width('87%') 215 .height('6%') 216 .fontWeight(500) 217 .fontSize(20) 218 .margin({ bottom: '24vp' }) 219 .onClick(() => { 220 item.clickMethod(); 221 }) 222 }, item => JSON.stringify(item)) 223 } 224 } 225 226 // 在foreach中渲染Button组件时传入不同按钮的参数 227 getButtonItemValues() { 228 let values: Array<ButtonItemData> = [ 229 new ButtonItemData( 230 '保存数据', 231 () => { 232 // 调用保存方法 233 PreferenceModel.writeData(this.screenBrightness); 234 } 235 ), 236 new ButtonItemData( 237 '读取数据', 238 () => { 239 // 调用读取方法 240 PreferenceModel.getPreference().then(resultData => { 241 this.screenBrightness = resultData; 242 console.info('dbdata is '+JSON.stringify(resultData)) 243 }); 244 } 245 ), 246 new ButtonItemData( 247 '删除数据', 248 () => { 249 // 调用删除方法 250 PreferenceModel.deletePreferences(); 251 // 数据删除后将相关内容置为空 252 this.screenBrightness.brightSwitch = ''; 253 this.screenBrightness.defaultValue = '' 254 } 255 ) 256 ]; 257 return values; 258 } 259 } 260 ``` 2613. 构建首页UI。 262 在页面生命周期的aboutToAppear中调用自定义首选项类的getPreference方法获取到保存的数据,这样如果用户之前有保存数据的话,进入应用中就可以显示之前保存的数据。 263 具体代码如下: 264 ```ts 265 import PreferenceModel from '../model/PreferenceModel'; 266 import ButtonComponent from '../view/ButtonComponent'; 267 import TextItemComponent from '../view/TextItemComponent'; 268 import ScreenBrightness from '../common/bean/Brightness'; 269 270 @Entry 271 @Component 272 struct Setting { 273 @State screenBrightness: ScreenBrightness = new ScreenBrightness('', ''); 274 275 build() { 276 Column() { 277 // 亮度调节文本及文本框 278 TextItemComponent({ 279 textResource: $r('app.string.brightness_text'), 280 placeholderResource: $r('app.string.brightness_placeholder'), 281 textFlag: 0, 282 screenBrightness: $screenBrightness, 283 textInputCallBack: (value) => { 284 this.screenBrightness.brightSwitch = value; 285 } 286 }) 287 288 // 设定值文本及文本框 289 TextItemComponent({ 290 textResource: $r('app.string.defaultValue_text'), 291 placeholderResource: $r('app.string.defaultValue_placeholder'), 292 textFlag: 1, 293 screenBrightness: $screenBrightness, 294 textInputCallBack: (value) => { 295 this.screenBrightness.defaultValue = value; 296 } 297 }) 298 299 // 按钮 300 ButtonComponent({ screenBrightness: $screenBrightness }) 301 } 302 .width('100%') 303 .height('100%') 304 .backgroundColor("#F1F3F5") 305 } 306 307 async aboutToAppear() { 308 await PreferenceModel.getPreferencesFromStorage(); 309 // 获取到之前保存的数据,显示在输入框中 310 PreferenceModel.getPreference().then(resultData => { 311 this.screenBrightness = resultData; 312 }); 313 } 314 } 315 ``` 316 317## 完整代码 318由于开发步骤中已经展示了大部分完整代码,此处补充前文中未呈现的两个数据类: 319亮度数据类: 320```ts 321export default class ScreenBrightness { 322 // 亮度调节 323 brightSwitch: string; 324 // 设定值 325 defaultValue: string; 326 327 constructor(brightSwitch: string, defaultValue: string) { 328 this.brightSwitch = brightSwitch; 329 this.defaultValue = defaultValue; 330 } 331} 332``` 333按钮数据类: 334```ts 335export default class ButtonItemData { 336 337 // 按钮文本 338 text: string; 339 340 // 按钮点击事件触发的方法 341 clickMethod: () => void; 342 343 constructor(text: string, clickMethod: () => void) { 344 this.text = text; 345 this.clickMethod = clickMethod; 346 } 347} 348``` 349 350## 参考 351- [@ohos.data.preferences (用户首选项)](../application-dev/reference/apis-arkdata/js-apis-data-preferences.md) 352- [通过用户首选项实现数据持久化](../application-dev/database/data-persistence-by-preferences.md)