1# 通过用户首选项实现数据持久化 (C/C++)
2
3## 场景介绍
4用户首选项(Preferences)模块主要提供轻量级Key-Value操作,支持本地应用存储少量数据,数据存储在本地文件中,同时也加载在内存中,所以访问速度更快,效率更高。首选项提供非关系型数据存储,不宜存储大量数据,经常用于操作键值对形式数据的场景。
5
6
7## 约束限制
8Preferences不支持C API与ArkTS API混合使用。
9
10
11## 接口说明
12
13详细的接口说明请参考[Preferences接口文档](../reference/apis-arkdata/_preferences.md)。
14
15| 接口名称 | 描述 |
16| -------- | -------- |
17| OH_Preferences \* OH_Preferences_Open (OH_PreferencesOption \*option, int \*errCode) | 打开一个Preferences实例对象并创建指向它的指针。 当不再需要使用指针时,请使用OH_Preferences_Close关闭实例对象。 |
18| int OH_Preferences_Close (OH_Preferences \*preference) | 关闭一个Preferences实例对象。 |
19| int OH_Preferences_GetInt (OH_Preferences \*preference, const char \*key, int \*value) | 获取Preferences实例对象中Key对应的整型值。 |
20| int OH_Preferences_GetBool (OH_Preferences \*preference, const char \*key, bool \*value) | 获取Preferences实例对象中Key对应的布尔值。 |
21| int OH_Preferences_GetString (OH_Preferences \*preference, const char \*key, char \*\*value, uint32_t \*valueLen) | 获取Preferences实例对象中Key对应的字符串。 |
22| void OH_Preferences_FreeString (char \*string) | 释放从Preferences实例对象中获取的字符串。 |
23| int OH_Preferences_SetInt (OH_Preferences \*preference, const char \*key, int value) | 根据Key设置Preferences实例对象中的整型值。 |
24| int OH_Preferences_SetBool (OH_Preferences \*preference, const char \*key, bool value) | 根据Key设置Preferences实例对象中的布尔值。 |
25| int OH_Preferences_SetString (OH_Preferences \*preference, const char \*key, const char \*value) | 根据Key设置Preferences实例对象中的字符串。 |
26| int OH_Preferences_Delete (OH_Preferences \*preference, const char \*key) | 在Preferences实例对象中删除Key对应的KV数据。 |
27| int OH_Preferences_RegisterDataObserver (OH_Preferences \*preference, void \*context, OH_PreferencesDataObserver observer, const char \*keys[], uint32_t keyCount) | 对选取的Key注册数据变更订阅。订阅的Key的值发生变更后,在调用OH_Preferences_Close()后触发回调。 |
28| int OH_Preferences_UnregisterDataObserver (OH_Preferences \*preference, void \*context, OH_PreferencesDataObserver observer, const char \*keys[], uint32_t keyCount) | 取消注册选取Key的数据变更订阅。 |
29| OH_PreferencesOption \* OH_PreferencesOption_Create (void) | 创建一个Preferences配置选项的OH_PreferencesOption实例对象以及指向它的指针。 当不再需要使用指针时,请使用OH_PreferencesOption_Destroy销毁实例对象,否则会导致内存泄漏。 |
30| int OH_PreferencesOption_SetFileName (OH_PreferencesOption \*option, const char \*fileName) | 设置Preferences配置选项OH_PreferencesOption实例对象的文件名称。 |
31| int OH_PreferencesOption_SetBundleName (OH_PreferencesOption \*option, const char \*bundleName) | 设置Preferences配置选项OH_PreferencesOption实例对象的包名称。 |
32| int OH_PreferencesOption_SetDataGroupId (OH_PreferencesOption \*option, const char \*dataGroupId) | 设置Preferences配置选项OH_PreferencesOption实例对象的应用组ID。 |
33| int OH_PreferencesOption_Destroy (OH_PreferencesOption \*option) | 销毁Preferences配置选项OH_PreferencesOption实例。 |
34| const char \* OH_PreferencesPair_GetKey (const OH_PreferencesPair \*pairs, uint32_t index) | 获取KV数据中索引对应数据的键。 |
35| const OH_PreferencesValue \* OH_PreferencesPair_GetPreferencesValue (const OH_PreferencesPair \*pairs, uint32_t index) | 获取KV数据数组中索引对应的值。 |
36| Preference_ValueType OH_PreferencesValue_GetValueType (const OH_PreferencesValue \*object) | 获取PreferencesValue对象的数据类型。 |
37| int OH_PreferencesValue_GetInt (const OH_PreferencesValue \*object, int \*value) | 从PreferencesValue对象OH_PreferencesValue中获取一个整型值。 |
38| int OH_PreferencesValue_GetBool (const OH_PreferencesValue \*object, bool \*value) | 从PreferencesValue对象OH_PreferencesValue中获取一个布尔值。 |
39| int OH_PreferencesValue_GetString (const OH_PreferencesValue \*object, char \*\*value, uint32_t \*valueLen) | 从PreferencesValue对象OH_PreferencesValue中获取字符串。 |
40
41
42## 添加动态链接库
43
44CMakeLists.txt中添加以下lib。
45
46```txt
47libohpreferences.so
48```
49
50## 引用头文件
51
52```c
53#include <cstring>
54#include <database/preferences/oh_preferences.h>
55#include <database/preferences/oh_preferences_err_code.h>
56#include <database/preferences/oh_preferences_option.h>
57#include <database/preferences/oh_preferences_value.h>
58```
59
60## 开发步骤
61下列实例展示如何通过Preferences实现对KV数据的修改与持久化。
621. 创建Preferences配置选项(PreferencesOption)对象并设置配置选项成员,配置选项实例使用完后需要调用OH_PreferencesOption_Destroy销毁。
632. 调用OH_Preferences_Open打开一个Preferences实例,该实例使用完后需要调用OH_Preferences_Close关闭。
643. 调用OH_Preferences_RegisterDataObserver注册3个Key的数据变更订阅,订阅回调函数为DataChangeObserverCallback。
654. 设置Preferences实例中的KV数据。
665. 获取Preferences实例中的KV数据。
676. 调用OH_Preferences_Close关闭Preferences实例,关闭后需要将实例指针置空。
68
69```c
70// 数据变更回调函数
71void DataChangeObserverCallback(void *context, const OH_PreferencesPair *pairs, uint32_t count) {
72    for (uint32_t i = 0; i < count; i++) {
73        // 获取索引i对应的PreferenceValue
74        const OH_PreferencesValue *pValue = OH_PreferencesPair_GetPreferencesValue(pairs, i);
75        // 获取PreferencesValue的数据类型
76        Preference_ValueType type = OH_PreferencesValue_GetValueType(pValue);
77        int ret = PREFERENCES_OK;
78        if (type == PREFERENCE_TYPE_INT) {
79            int intValue = 0;
80            ret = OH_PreferencesValue_GetInt(pValue, &intValue);
81            if (ret == PREFERENCES_OK) {
82                // 业务逻辑
83            }
84        } else if (type == PREFERENCE_TYPE_BOOL) {
85            bool boolValue = true;
86            ret = OH_PreferencesValue_GetBool(pValue, &boolValue);
87            if (ret == PREFERENCES_OK) {
88                // 业务逻辑
89            }
90        } else if (type == PREFERENCE_TYPE_STRING) {
91            char *stringValue = nullptr;
92            uint32_t valueLen = 0;
93            ret = OH_PreferencesValue_GetString(pValue, &stringValue, &valueLen);
94            if (ret == PREFERENCES_OK) {
95                // 业务逻辑
96                OH_Preferences_FreeString(stringValue);
97            }
98        } else {
99            // 无效类型
100        }
101    }
102}
103
104// 1. 创建Preferences配置选项。
105OH_PreferencesOption *option = OH_PreferencesOption_Create();
106if (option == nullptr) {
107    // 错误处理
108}
109// 设置Preferences配置选项的文件名称。
110int ret = OH_PreferencesOption_SetFileName(option, "testdb");
111if (ret != PREFERENCES_OK) {
112    (void)OH_PreferencesOption_Destroy(option);
113    // 错误处理
114}
115// 设置Preferences配置选项的应用组ID。
116ret = OH_PreferencesOption_SetDataGroupId(option, "");
117if (ret != PREFERENCES_OK) {
118    (void)OH_PreferencesOption_Destroy(option);
119    // 错误处理
120}
121// 设置Preferences配置选项的包名称。
122ret = OH_PreferencesOption_SetBundleName(option, "com.example");
123if (ret != PREFERENCES_OK) {
124    (void)OH_PreferencesOption_Destroy(option);
125    // 错误处理
126}
127
128// 2. 打开一个Preferences实例。
129int errCode = PREFERENCES_OK;
130OH_Preferences *preference = OH_Preferences_Open(option, &errCode);
131// option使用完毕后可直接释放,释放后需要将指针置空。
132(void)OH_PreferencesOption_Destroy(option);
133option = nullptr;
134if (preference == nullptr) {
135    // 错误处理
136}
137
138// 3. 对key_int、key_bool和key_string注册数据变更订阅。
139const char *keys[] = {"key_int", "key_bool", "key_string"};
140ret = OH_Preferences_RegisterDataObserver(preference, nullptr, DataChangeObserverCallback, keys, 3);
141if (ret != PREFERENCES_OK) {
142    (void)OH_Preferences_Close(preference);
143    // 错误处理
144}
145
146// 4. 设置Preferences实例中的KV数据。
147ret = OH_Preferences_SetInt(preference, keys[0], 0);
148if (ret != PREFERENCES_OK) {
149    (void)OH_Preferences_Close(preference);
150    // 错误处理
151}
152ret = OH_Preferences_SetBool(preference, keys[1], true);
153if (ret != PREFERENCES_OK) {
154    (void)OH_Preferences_Close(preference);
155    // 错误处理
156}
157ret = OH_Preferences_SetString(preference, keys[2], "string value");
158if (ret != PREFERENCES_OK) {
159    (void)OH_Preferences_Close(preference);
160    // 错误处理
161}
162
163// 5. 获取Preferences实例中的KV数据。
164int intValue = 0;
165ret = OH_Preferences_GetInt(preference, keys[0], &intValue);
166if (ret == PREFERENCES_OK) {
167    // 业务逻辑
168}
169
170bool boolValue = false;
171ret = OH_Preferences_GetBool(preference, keys[1], &boolValue);
172if (ret == PREFERENCES_OK) {
173    // 业务逻辑
174}
175
176char *stringValue = nullptr;
177uint32_t valueLen = 0;
178ret = OH_Preferences_GetString(preference, keys[2], &stringValue, &valueLen);
179if (ret == PREFERENCES_OK) {
180    // 业务逻辑
181    // 使用完OH_Preferences_GetString接口后,需要对字符串进行释放。
182    OH_Preferences_FreeString(stringValue);
183    stringValue = nullptr;
184}
185
186// 6. 使用完Preferences实例后需要关闭实例,关闭后需要将指针置空。
187(void)OH_Preferences_Close(preference);
188preference = nullptr;
189
190```
191