1# 通过用户首选项实现数据持久化 (C/C++) 2<!--Kit: ArkData--> 3<!--Subsystem: DistributedDataManager--> 4<!--Owner: @yanhuii--> 5<!--Designer: @houpengtao1--> 6<!--Tester: @yippo; @logic42--> 7<!--Adviser: @ge-yafang--> 8 9## 场景介绍 10用户首选项(Preferences)模块主要提供轻量级Key-Value操作,支持本地存储少量数据,数据存储在文件和内存中,访问速度快。如果存在大量数据场景,请考虑使用键值型数据库或关系型数据库。 11 12## 约束限制 13- API version 18之前:ArkTS API仅支持[XML存储模式](./data-persistence-by-preferences.md#xml存储);C API仅支持[GSKV存储模式](./data-persistence-by-preferences.md#gskv存储);存储模式互不兼容,不支持ArkTS和C API操作同一个Preferences实例。 14- API version 18及之后:ArkTS和C API均支持XML和GSKV双模式;ArkTS和C API使用相同的存储模式时,可以正常操作同一Preferences实例;禁止ArkTS和C API选择不同的存储模式,来操作同一个Preferences实例。 15- Key的最大长度限制为1024个字节,Value的最大长度限制为16MB。 16 17 18## 接口说明 19 20详细的接口说明请参考[Preferences接口文档](../reference/apis-arkdata/capi-preferences.md)。 21 22| 接口名称 | 描述 | 23| -------- | -------- | 24| OH_Preferences \* OH_Preferences_Open (OH_PreferencesOption \*option, int \*errCode) | 打开一个Preferences实例对象并创建指向它的指针。 当不再需要使用指针时,请使用OH_Preferences_Close关闭实例对象。 | 25| int OH_Preferences_Close (OH_Preferences \*preference) | 关闭一个Preferences实例对象。 | 26| int OH_Preferences_GetInt (OH_Preferences \*preference, const char \*key, int \*value) | 获取Preferences实例对象中Key对应的整型值。 | 27| int OH_Preferences_GetBool (OH_Preferences \*preference, const char \*key, bool \*value) | 获取Preferences实例对象中Key对应的布尔值。 | 28| int OH_Preferences_GetString (OH_Preferences \*preference, const char \*key, char \*\*value, uint32_t \*valueLen) | 获取Preferences实例对象中Key对应的字符串。 | 29| void OH_Preferences_FreeString (char \*string) | 释放从Preferences实例对象中获取的字符串。 | 30| int OH_Preferences_SetInt (OH_Preferences \*preference, const char \*key, int value) | 根据Key设置Preferences实例对象中的整型值。 | 31| int OH_Preferences_SetBool (OH_Preferences \*preference, const char \*key, bool value) | 根据Key设置Preferences实例对象中的布尔值。 | 32| int OH_Preferences_SetString (OH_Preferences \*preference, const char \*key, const char \*value) | 根据Key设置Preferences实例对象中的字符串。 | 33| int OH_Preferences_Delete (OH_Preferences \*preference, const char \*key) | 在Preferences实例对象中删除Key对应的KV数据。 | 34| int OH_Preferences_RegisterDataObserver (OH_Preferences \*preference, void \*context, OH_PreferencesDataObserver observer, const char \*keys[], uint32_t keyCount) | 对选取的Key注册数据变更订阅。订阅的Key的值发生变更后,在调用OH_Preferences_Close()后触发回调。 | 35| int OH_Preferences_UnregisterDataObserver (OH_Preferences \*preference, void \*context, OH_PreferencesDataObserver observer, const char \*keys[], uint32_t keyCount) | 取消注册选取Key的数据变更订阅。 | 36| int OH_Preferences_IsStorageTypeSupported (Preferences_StorageType type, bool \*isSupported) | 检查当前平台是否支持对应的存储模式。 | 37| OH_PreferencesOption \* OH_PreferencesOption_Create (void) | 创建一个Preferences配置选项的OH_PreferencesOption实例对象以及指向它的指针。 当不再需要使用指针时,请使用OH_PreferencesOption_Destroy销毁实例对象,否则会导致内存泄漏。 | 38| int OH_PreferencesOption_SetFileName (OH_PreferencesOption \*option, const char \*fileName) | 设置Preferences配置选项OH_PreferencesOption实例对象的文件名称。名称长度为0到255字节,其中不能包含'/'。 | 39| int OH_PreferencesOption_SetBundleName (OH_PreferencesOption \*option, const char \*bundleName) | 设置Preferences配置选项OH_PreferencesOption实例对象的包名称。 | 40| int OH_PreferencesOption_SetDataGroupId (OH_PreferencesOption \*option, const char \*dataGroupId) | 设置Preferences配置选项OH_PreferencesOption实例对象的应用组ID。 | 41| int OH_PreferencesOption_SetStorageType (OH_PreferencesOption \*option, Preferences_StorageType type) | 设置Preferences配置选项 OH_PreferencesOption实例对象的存储模式。 | 42| int OH_PreferencesOption_Destroy (OH_PreferencesOption \*option) | 销毁Preferences配置选项OH_PreferencesOption实例。 | 43| const char \* OH_PreferencesPair_GetKey (const OH_PreferencesPair \*pairs, uint32_t index) | 获取KV数据中索引对应数据的键。 | 44| const OH_PreferencesValue \* OH_PreferencesPair_GetPreferencesValue (const OH_PreferencesPair \*pairs, uint32_t index) | 获取KV数据数组中索引对应的值。 | 45| Preference_ValueType OH_PreferencesValue_GetValueType (const OH_PreferencesValue \*object) | 获取PreferencesValue对象的数据类型。 | 46| int OH_PreferencesValue_GetInt (const OH_PreferencesValue \*object, int \*value) | 从PreferencesValue对象OH_PreferencesValue中获取一个整型值。 | 47| int OH_PreferencesValue_GetBool (const OH_PreferencesValue \*object, bool \*value) | 从PreferencesValue对象OH_PreferencesValue中获取一个布尔值。 | 48| int OH_PreferencesValue_GetString (const OH_PreferencesValue \*object, char \*\*value, uint32_t \*valueLen) | 从PreferencesValue对象OH_PreferencesValue中获取字符串。 | 49 50 51## 添加动态链接库 52 53CMakeLists.txt中添加以下lib。 54 55```txt 56libohpreferences.so 57``` 58 59## 引用头文件 60 61```c 62#include <cstring> 63#include <database/preferences/oh_preferences.h> 64#include <database/preferences/oh_preferences_err_code.h> 65#include <database/preferences/oh_preferences_option.h> 66#include <database/preferences/oh_preferences_value.h> 67``` 68 69## 开发步骤 70下列实例展示如何通过Preferences实现对键值数据的修改与持久化。 711. 创建Preferences配置选项(PreferencesOption)对象并设置配置选项成员(名称、应用组ID、包名、存储模式)。使用完毕后,调用OH_PreferencesOption_Destroy销毁配置选项实例。 722. 调用OH_Preferences_Open打开一个Preferences实例,该实例使用完后需要调用OH_Preferences_Close关闭。 733. 调用OH_Preferences_RegisterDataObserver注册3个Key的数据变更订阅,订阅回调函数为DataChangeObserverCallback。 744. 设置Preferences实例中的键值数据。 755. 获取Preferences实例中的键值数据。 766. 调用OH_Preferences_Close关闭Preferences实例,关闭后需要将实例指针置空。 77 78```c 79// 数据变更回调函数 80void DataChangeObserverCallback(void *context, const OH_PreferencesPair *pairs, uint32_t count) { 81 for (uint32_t i = 0; i < count; i++) { 82 // 获取索引i对应的PreferenceValue 83 const OH_PreferencesValue *pValue = OH_PreferencesPair_GetPreferencesValue(pairs, i); 84 // 获取PreferencesValue的数据类型 85 Preference_ValueType type = OH_PreferencesValue_GetValueType(pValue); 86 int ret = PREFERENCES_OK; 87 if (type == PREFERENCE_TYPE_INT) { 88 int intValue = 0; 89 ret = OH_PreferencesValue_GetInt(pValue, &intValue); 90 if (ret == PREFERENCES_OK) { 91 // 业务逻辑 92 } 93 } else if (type == PREFERENCE_TYPE_BOOL) { 94 bool boolValue = true; 95 ret = OH_PreferencesValue_GetBool(pValue, &boolValue); 96 if (ret == PREFERENCES_OK) { 97 // 业务逻辑 98 } 99 } else if (type == PREFERENCE_TYPE_STRING) { 100 char *stringValue = nullptr; 101 uint32_t valueLen = 0; 102 ret = OH_PreferencesValue_GetString(pValue, &stringValue, &valueLen); 103 if (ret == PREFERENCES_OK) { 104 // 业务逻辑 105 OH_Preferences_FreeString(stringValue); 106 } 107 } else { 108 // 无效类型 109 } 110 } 111} 112 113// 1. 创建Preferences配置选项。 114OH_PreferencesOption *option = OH_PreferencesOption_Create(); 115if (option == nullptr) { 116 // 错误处理 117} 118// 设置Preferences配置选项的文件名称。 119int ret = OH_PreferencesOption_SetFileName(option, "testdb"); 120if (ret != PREFERENCES_OK) { 121 (void)OH_PreferencesOption_Destroy(option); 122 // 错误处理 123} 124// 设置Preferences配置选项的应用组ID。 125ret = OH_PreferencesOption_SetDataGroupId(option, ""); 126if (ret != PREFERENCES_OK) { 127 (void)OH_PreferencesOption_Destroy(option); 128 // 错误处理 129} 130// 设置Preferences配置选项的包名称。 131ret = OH_PreferencesOption_SetBundleName(option, "com.example"); 132if (ret != PREFERENCES_OK) { 133 (void)OH_PreferencesOption_Destroy(option); 134 // 错误处理 135} 136 137// 设置Preferences配置选项的存储模式,需要注意的是,设置之前需要调用OH_Preferences_IsStorageTypeSupported接口判断当前平台是否支持需要选择的模式。 138bool isGskvSupported = false; 139ret = OH_Preferences_IsStorageTypeSupported(Preferences_StorageType::PREFERENCES_STORAGE_GSKV, &isGskvSupported); 140if (ret != PREFERENCES_OK) { 141 (void)OH_PreferencesOption_Destroy(option); 142 // 错误处理 143} 144if (isGskvSupported) { 145 ret = OH_PreferencesOption_SetStorageType(option, Preferences_StorageType::PREFERENCES_STORAGE_GSKV); 146 if (ret != PREFERENCES_OK) { 147 (void)OH_PreferencesOption_Destroy(option); 148 // 错误处理 149 } 150} else { 151 ret = OH_PreferencesOption_SetStorageType(option, Preferences_StorageType::PREFERENCES_STORAGE_XML); 152 if (ret != PREFERENCES_OK) { 153 (void)OH_PreferencesOption_Destroy(option); 154 // 错误处理 155 } 156} 157 158// 2. 打开一个Preferences实例。 159int errCode = PREFERENCES_OK; 160OH_Preferences *preference = OH_Preferences_Open(option, &errCode); 161// option使用完毕后可直接释放,释放后需要将指针置空。 162(void)OH_PreferencesOption_Destroy(option); 163option = nullptr; 164if (preference == nullptr || errCode != PREFERENCES_OK) { 165 // 错误处理 166} 167 168// 3. 对key_int、key_bool和key_string注册数据变更订阅。 169const char *keys[] = {"key_int", "key_bool", "key_string"}; 170ret = OH_Preferences_RegisterDataObserver(preference, nullptr, DataChangeObserverCallback, keys, 3); 171if (ret != PREFERENCES_OK) { 172 (void)OH_Preferences_Close(preference); 173 // 错误处理 174} 175 176// 4. 设置Preferences实例中的KV数据。 177ret = OH_Preferences_SetInt(preference, keys[0], 0); 178if (ret != PREFERENCES_OK) { 179 (void)OH_Preferences_Close(preference); 180 // 错误处理 181} 182ret = OH_Preferences_SetBool(preference, keys[1], true); 183if (ret != PREFERENCES_OK) { 184 (void)OH_Preferences_Close(preference); 185 // 错误处理 186} 187ret = OH_Preferences_SetString(preference, keys[2], "string value"); 188if (ret != PREFERENCES_OK) { 189 (void)OH_Preferences_Close(preference); 190 // 错误处理 191} 192 193// 5. 获取Preferences实例中的KV数据。 194int intValue = 0; 195ret = OH_Preferences_GetInt(preference, keys[0], &intValue); 196if (ret == PREFERENCES_OK) { 197 // 业务逻辑 198} 199 200bool boolValue = false; 201ret = OH_Preferences_GetBool(preference, keys[1], &boolValue); 202if (ret == PREFERENCES_OK) { 203 // 业务逻辑 204} 205 206char *stringValue = nullptr; 207uint32_t valueLen = 0; 208ret = OH_Preferences_GetString(preference, keys[2], &stringValue, &valueLen); 209if (ret == PREFERENCES_OK) { 210 // 业务逻辑 211 // 使用完OH_Preferences_GetString接口后,需要对字符串进行释放。 212 OH_Preferences_FreeString(stringValue); 213 stringValue = nullptr; 214} 215 216// 6. 使用完Preferences实例后需要关闭实例,关闭后需要将指针置空。 217(void)OH_Preferences_Close(preference); 218preference = nullptr; 219 220``` 221