用户首选项使用
用户首选项的特点
数据体积小、访问频率高、有加载速度要求的数据如用户偏好设置、用户字体大小、应用的配置参数。
用户搜选项(Preferences)提供了轻量级配置数据的持久化能力,支持订阅数据变化的通知能力。不支持分布式同步。
基于Key-Value的数据结构,Key是不重复的关键字,Value是数据值。
Preferences是一种非关系型数据库,不遵循数据库的ACID特性,数据见毫无关系。
用户首选项存储在内存中,存储数据量过大会导致应用占用内存过多。如果需要持久化存储,可以调用Flush接口。
不支持数据加密。
用户首选项使用场景
应用配置参数、用户偏好设置,如应用字体大小个性化调整、主题颜色等。
用户首选项机制原理
用户首选项实际通过持久化文件的形式存储在应用沙箱目录中,ArkTS提供交互接口。每个持久化文件唯一关联一个实例。
用户程序通过UIAbilityContext来获得Preferences实例。 因为一个程序可以有多个UIAbility,所以可以获得多个Preferences实例。
用户首选项主要API
preferences.getPreferencesSync10+
getPreferencesSync(context: Context, options: Options): Preferences
获取Preferences实例,此为同步接口。
参数:
参数名 | 类型 | 必填 | 说明 |
---|---|---|---|
context | Context | 是 | 应用上下文。 FA模型的应用Context定义见Context。 Stage模型的应用Context定义见Context。 |
options | Options | 是 | 与Preferences实例相关的配置选项。 |
返回值:
类型 | 说明 |
---|---|
Preferences | 返回Preferences实例。 |
示例代码:
import { UIAbility } from '@kit.AbilityKit';
import { window } from '@kit.ArkUI';let dataPreferences: preferences.Preferences | null = null;class EntryAbility extends UIAbility {onWindowStageCreate(windowStage: window.WindowStage) {let options: preferences.Options = { name: 'myStore' };dataPreferences = preferences.getPreferencesSync(this.context, options);}
}
putSync10+
putSync(key: string, value: ValueType): void
将数据写入缓存的Preferences实例中,可通过flush将Preferences实例持久化,此为同步接口。
参数:
参数名 | 类型 | 必填 | 说明 |
---|---|---|---|
key | string | 是 | 要修改的存储的Key,不能为空。 |
value | ValueType | 是 | 存储的新值。 |
示例代码:
dataPreferences.putSync('startup', 'auto');
// 当字符串有特殊字符时,需要将字符串转为Uint8Array类型再存储
let uInt8Array1 = new util.TextEncoder().encodeInto("~!@#¥%……&*()——+?");
dataPreferences.putSync('uInt8', uInt8Array1);
hasSync10+
hasSync(key: string): boolean
检查缓存的Preferences实例中是否包含名为给定Key的存储键值对,此为同步接口。
参数:
参数名 | 类型 | 必填 | 说明 |
---|---|---|---|
key | string | 是 | 要检查的存储key名称,不能为空。 |
返回值:
类型 | 说明 |
---|---|
boolean | 返回Preferences实例是否包含给定key的存储键值对,true表示存在,false表示不存在。 |
示例代码:
let isExist: boolean = dataPreferences.hasSync('startup');
if (isExist) {console.info("The key 'startup' is contained.");
} else {console.info("The key 'startup' dose not contain.");
}
getSync10+
getSync(key: string, defValue: ValueType): ValueType
从缓存的Preferences实例中获取键对应的值,如果值为null或者非默认值类型,返回默认数据defValue,此为同步接口。
参数:
参数名 | 类型 | 必填 | 说明 |
---|---|---|---|
key | string | 是 | 要获取的存储Key名称,不能为空。 |
defValue | ValueType | 是 | 默认返回值。 |
返回值:
类型 | 说明 |
---|---|
ValueType | 返回键对应的值。 |
示例代码:
let value: preferences.ValueType = dataPreferences.getSync('startup', 'default');
deleteSync10+
deleteSync(key: string): void
从缓存的Preferences实例中删除名为给定Key的存储键值对,可通过flush将Preferences实例持久化,此为同步接口。
参数:
参数名 | 类型 | 必填 | 说明 |
---|---|---|---|
key | string | 是 | 要删除的存储key名称,不能为空。 |
示例代码:
dataPreferences.deleteSync('startup');
flush
flush(callback: AsyncCallback<void>): void
将缓存的Preferences实例中的数据异步存储到用户首选项的持久化文件中,使用callback异步回调。
参数:
参数名 | 类型 | 必填 | 说明 |
---|---|---|---|
callback | AsyncCallback<void> | 是 |
示例代码:
import { BusinessError } from '@kit.BasicServicesKit';dataPreferences.flush((err: BusinessError) => {if (err) {console.error("Failed to flush. code =" + err.code + ", message =" + err.message);return;}console.info("Succeeded in flushing.");
})
let promise = dataPreferences.flush();
promise.then(() => {console.info("Succeeded in flushing.");
}).catch((err: BusinessError) => {console.error("Failed to flush. code =" + err.code + ", message =" + err.message);
})
on('change')
on(type: 'change', callback: Callback<string>): void
订阅数据变更,订阅的Key的值发生变更后,在执行flush方法后,触发callback回调。
当调用removePreferencesFromCache或者deletePreferences后,订阅的数据变更会主动取消订阅,在重新getPreferences后需要重新订阅数据变更。
参数:
参数名 | 类型 | 必填 | 说明 |
---|---|---|---|
type | string | 是 | 事件类型,固定值'change',表示数据变更。 |
callback | Callback<string> | 是 | 回调函数。 |
示例代码:
let observer = (key: string) => {console.info('The key' + key + 'changed.');
}
dataPreferences.on('change', observer);
// 数据产生变更,由'auto'变为'manual'
dataPreferences.put('startup', 'manual', (err: BusinessError) => {if (err) {console.error(`Failed to put the value of 'startup'. Code:${err.code},message:${err.message}`);return;}console.info("Succeeded in putting the value of 'startup'.");if (dataPreferences !== null) {dataPreferences.flush((err: BusinessError) => {if (err) {console.error(`Failed to flush. Code:${err.code}, message:${err.message}`);return;}console.info('Succeeded in flushing.');})}
})
on('dataChange')12+
on(type: 'dataChange', keys: Array<string>, callback: Callback<Record<string, ValueType>>): void
精确订阅数据变更,只有被订阅的key值发生变更后,在执行flush方法后,触发callback回调。
参数:
参数名 | 类型 | 必填 | 说明 |
---|---|---|---|
type | string | 是 | 事件类型,固定值'dataChange',表示精确的数据变更。 |
keys | Array<string> | 是 | 需要订阅的key集合。 |
callback | Callback<Record<string, ValueType>> | 是 | 回调函数。回调支持返回多个键值对,其中键为发生变更的订阅key,值为变更后的数据:支持number、string、boolean、Array<number>、Array<string>、Array<boolean>、Uint8Array、object类型。 |
import { BusinessError } from '@kit.BasicServicesKit';let observer = (data: Record<string, preferences.ValueType>) => {for (const keyValue of Object.entries(data)) {console.info(`observer : ${keyValue}`)}console.info("The observer called.")
}
let keys = ['name', 'age']
dataPreferences.on('dataChange', keys, observer);
dataPreferences.putSync('name', 'xiaohong');
dataPreferences.putSync('weight', 125);
dataPreferences.flush((err: BusinessError) => {if (err) {console.error("Failed to flush. Cause: " + err);return;}console.info("Succeeded in flushing.");
})
off('change')
off(type: 'change', callback?: Callback<string>): void
取消订阅数据变更。
参数:
参数名 | 类型 | 必填 | 说明 |
---|---|---|---|
type | string | 是 | 事件类型,固定值'change',表示数据变更。 |
callback | Callback<string> | 否 |
示例代码:
import { BusinessError } from '@kit.BasicServicesKit';let observer = (key: string) => {console.info("The key " + key + " changed.");
}
dataPreferences.on('change', observer);
dataPreferences.putSync('startup', 'auto');
dataPreferences.flush((err: BusinessError) => {if (err) {console.error("Failed to flush. Cause: " + err);return;}console.info("Succeeded in flushing.");
})
dataPreferences.off('change', observer);
preferences.deletePreferences10+
deletePreferences(context: Context, options: Options, callback: AsyncCallback<void>): void
从缓存中移出指定的Preferences实例,若Preferences实例有对应的持久化文件,则同时删除其持久化文件。使用callback异步回调。
调用该接口后,不建议再使用旧的Preferences实例进行数据操作,否则会出现数据一致性问题,应将Preferences实例置为null,系统将会统一回收。
不支持该接口与preference其他接口并发调用。
参数:
参数名 | 类型 | 必填 | 说明 |
---|---|---|---|
context | Context | 是 | 应用上下文。 FA模型的应用Context定义见Context。 Stage模型的应用Context定义见Context。 |
options | Options | 是 | 与Preferences实例相关的配置选项。 |
callback | AsyncCallback<void> | 是 | 回调函数。当移除成功,err为undefined,否则为错误对象。 |
示例代码:
import { UIAbility } from '@kit.AbilityKit';
import { BusinessError } from '@kit.BasicServicesKit';
import { window } from '@kit.ArkUI';class EntryAbility extends UIAbility {onWindowStageCreate(windowStage: window.WindowStage) {let options: preferences.Options = { name: 'myStore' };preferences.deletePreferences(this.context, options, (err: BusinessError) => {if (err) {console.error("Failed to delete preferences. code =" + err.code + ", message =" + err.message);return;}console.info("Succeeded in deleting preferences.");})}
}
用户首选项开发流程
1. 导入模块
import { preferences } from '@kit.ArkData';
2. 获取preferences实例
import { UIAbility } from '@kit.AbilityKit';
import { window } from '@kit.ArkUI';let dataPreferences: preferences.Preferences | null = null;class EntryAbility extends UIAbility {onWindowStageCreate(windowStage: window.WindowStage) {let options: preferences.Options = { name: 'myStore' };dataPreferences = preferences.getPreferencesSync(this.context, options);}
}
3. 保存数据
dataPreferences.putSync('startup', 'auto');
4. 读取数据
dataPreferences.getSync('startup', 'default');
5. 数据持久化
import { BusinessError } from '@kit.BasicServicesKit';dataPreferences.flush((err: BusinessError) => {if (err) {console.error("Failed to flush. code =" + err.code + ", message =" + err.message);return;}console.info("Succeeded in flushing.");
})
用户首选项开发实践
用户首选项开发实践文档华为开发者学堂https://developer.huawei.com/consumer/cn/training/course/slightMooc/C101717498132814493
关系型数据库使用
关系型数据库简介
关系型数据库基于SQLite组件,适用于存储包含复杂关系数据的场景。关系型数据库对应用提供通用的操作接口,底层使用SQLite作为持久化存储引擎,支持SQLite具有的数据库特性,包括但不限于事务、索引、视图、触发器、外键、参数化查询和预编译SQL语句。
关系型数据库主要API
relationalStore.getRdbStore
getRdbStore(context: Context, config: StoreConfig, callback: AsyncCallback<RdbStore>): void
获得一个相关的RdbStore,操作关系型数据库,用户可以根据自己的需求配置RdbStore的参数,然后通过RdbStore调用相关接口可以执行相关的数据操作,使用callback异步回调。
当用非加密方式打开一个已有的加密数据库时,会返回错误码14800011,表示数据库损坏。此时用加密方式可以正常打开该数据库。
getRdbStore目前不支持多线程并发操作。
参数:
参数名 | 类型 | 必填 | 说明 |
---|---|---|---|
context | Context | 是 | 应用的上下文。 FA模型的应用Context定义见Context。 Stage模型的应用Context定义见Context。 |
config | StoreConfig | 是 | 与此RDB存储相关的数据库配置。 |
callback | AsyncCallback<RdbStore> | 是 | 指定callback回调函数,返回RdbStore对象。 |
示例代码:
import { UIAbility } from '@kit.AbilityKit';
import { window } from '@kit.ArkUI';
import { BusinessError } from '@kit.BasicServicesKit';let store: relationalStore.RdbStore | undefined = undefined;class EntryAbility extends UIAbility {onWindowStageCreate(windowStage: window.WindowStage) {const STORE_CONFIG: relationalStore.StoreConfig = {name: "RdbTest.db",securityLevel: relationalStore.SecurityLevel.S1};relationalStore.getRdbStore(this.context, STORE_CONFIG, (err: BusinessError, rdbStore: relationalStore.RdbStore) => {store = rdbStore;if (err) {console.error(`Get RdbStore failed, code is ${err.code},message is ${err.message}`);return;}console.info('Get RdbStore successfully.');})}
}
executeSql10+
executeSql(sql: string, callback: AsyncCallback<void>):void
执行包含指定参数但不返回值的SQL语句,语句中的各种表达式和操作符之间的关系操作符号不超过1000个,使用callback异步回调。
此接口不支持执行查询、附加数据库和事务操作,可以使用querySql、query、attach、beginTransaction、commit等接口代替。
不支持分号分隔的多条语句。
参数:
参数名 | 类型 | 必填 | 说明 |
---|---|---|---|
sql | string | 是 | 指定要执行的SQL语句。 |
callback | AsyncCallback<void> | 是 | 指定callback回调函数。 |
示例代码:
const SQL_DELETE_TABLE = "DELETE FROM test WHERE name = 'zhangsan'"if(store != undefined) {(store as relationalStore.RdbStore).executeSql(SQL_DELETE_TABLE, (err) => {if (err) {console.error(`ExecuteSql failed, code is ${err.code},message is ${err.message}`);return;}console.info('Delete table done.');})
}
insert
insert(table: string, values: ValuesBucket, callback: AsyncCallback<number>):void
向目标表中插入一行数据,使用callback异步回调。由于共享内存大小限制为2Mb,因此单条数据的大小需小于2Mb,否则会查询失败。
参数:
参数名 | 类型 | 必填 | 说明 |
---|---|---|---|
table | string | 是 | 指定的目标表名。 |
values | ValuesBucket | 是 | 表示要插入到表中的数据行。 |
callback | AsyncCallback<number> | 是 | 指定callback回调函数。如果操作成功,返回行ID;否则返回-1。 |
示例代码:
let value1 = "Lisa";
let value2 = 18;
let value3 = 100.5;
let value4 = new Uint8Array([1, 2, 3, 4, 5]);// 以下三种方式可用
const valueBucket1: relationalStore.ValuesBucket = {'NAME': value1,'AGE': value2,'SALARY': value3,'CODES': value4,
};
const valueBucket2: relationalStore.ValuesBucket = {NAME: value1,AGE: value2,SALARY: value3,CODES: value4,
};
const valueBucket3: relationalStore.ValuesBucket = {"NAME": value1,"AGE": value2,"SALARY": value3,"CODES": value4,
};if(store != undefined) {(store as relationalStore.RdbStore).insert("EMPLOYEE", valueBucket1, (err: BusinessError, rowId: number) => {if (err) {console.error(`Insert is failed, code is ${err.code},message is ${err.message}`);return;}console.info(`Insert is successful, rowId = ${rowId}`);})
}
update
update(values: ValuesBucket, predicates: RdbPredicates, callback: AsyncCallback<number>):void
根据RdbPredicates的指定实例对象更新数据库中的数据,使用callback异步回调。由于共享内存大小限制为2Mb,因此单条数据的大小需小于2Mb,否则会查询失败。
参数:
参数名 | 类型 | 必填 | 说明 |
---|---|---|---|
values | ValuesBucket | 是 | values指示数据库中要更新的数据行。键值对与数据库表的列名相关联。 |
predicates | RdbPredicates | 是 | RdbPredicates的实例对象指定的更新条件。 |
callback | AsyncCallback<number> | 是 | 指定的callback回调方法。返回受影响的行数。 |
示例代码:
let value1 = "Rose";
let value2 = 22;
let value3 = 200.5;
let value4 = new Uint8Array([1, 2, 3, 4, 5]);// 以下三种方式可用
const valueBucket1: relationalStore.ValuesBucket = {'NAME': value1,'AGE': value2,'SALARY': value3,'CODES': value4,
};
const valueBucket2: relationalStore.ValuesBucket = {NAME: value1,AGE: value2,SALARY: value3,CODES: value4,
};
const valueBucket3: relationalStore.ValuesBucket = {"NAME": value1,"AGE": value2,"SALARY": value3,"CODES": value4,
};let predicates = new relationalStore.RdbPredicates("EMPLOYEE");
predicates.equalTo("NAME", "Lisa");
if(store != undefined) {(store as relationalStore.RdbStore).update(valueBucket1, predicates,(err, rows) => {if (err) {console.error(`Updated failed, code is ${err.code},message is ${err.message}`);return;}console.info(`Updated row count: ${rows}`);})
}
delete
delete(predicates: RdbPredicates, callback: AsyncCallback<number>):void
根据RdbPredicates的指定实例对象从数据库中删除数据,使用callback异步回调。
参数:
参数名 | 类型 | 必填 | 说明 |
---|---|---|---|
predicates | RdbPredicates | 是 | RdbPredicates的实例对象指定的删除条件。 |
callback | AsyncCallback<number> | 是 | 指定callback回调函数。返回受影响的行数。 |
示例代码:
let predicates = new relationalStore.RdbPredicates("EMPLOYEE");
predicates.equalTo("NAME", "Lisa");
if(store != undefined) {(store as relationalStore.RdbStore).delete(predicates, (err, rows) => {if (err) {console.error(`Delete failed, code is ${err.code},message is ${err.message}`);return;}console.info(`Delete rows: ${rows}`);})
}
query10+
query(predicates: RdbPredicates, callback: AsyncCallback<ResultSet>):void
根据指定条件查询数据库中的数据,使用callback异步回调。由于共享内存大小限制为2Mb,因此单条数据的大小需小于2Mb,否则会查询失败。
参数:
参数名 | 类型 | 必填 | 说明 |
---|---|---|---|
predicates | RdbPredicates | 是 | RdbPredicates的实例对象指定的查询条件。 |
callback | AsyncCallback<ResultSet> | 是 | 指定callback回调函数。如果操作成功,则返回ResultSet对象。 |
let predicates = new relationalStore.RdbPredicates("EMPLOYEE");
predicates.equalTo("NAME", "Rose");
if(store != undefined) {(store as relationalStore.RdbStore).query(predicates, (err, resultSet) => {if (err) {console.error(`Query failed, code is ${err.code},message is ${err.message}`);return;}console.info(`ResultSet column names: ${resultSet.columnNames}, column count: ${resultSet.columnCount}`);// resultSet是一个数据集合的游标,默认指向第-1个记录,有效的数据从0开始。while (resultSet.goToNextRow()) {const id = resultSet.getLong(resultSet.getColumnIndex("ID"));const name = resultSet.getString(resultSet.getColumnIndex("NAME"));const age = resultSet.getLong(resultSet.getColumnIndex("AGE"));const salary = resultSet.getDouble(resultSet.getColumnIndex("SALARY"));console.info(`id=${id}, name=${name}, age=${age}, salary=${salary}`);}// 释放数据集的内存,若不释放可能会引起fd泄露与内存泄露resultSet.close();})
}
relationalStore.deleteRdbStore10+
deleteRdbStore(context: Context, config: StoreConfig, callback: AsyncCallback<void>): void
使用指定的数据库文件配置删除数据库,使用callback异步回调。
删除成功后,建议将数据库对象置为null。若数据库文件处于公共沙箱目录下,则删除数据库时必须使用该接口,当存在多个进程操作同一个数据库的情况,建议向其他进程发送数据库删除通知使其感知并处理。建立数据库时,若在StoreConfig中配置了自定义路径,则必须调用此接口进行删库。
参数:
参数名 | 类型 | 必填 | 说明 |
---|---|---|---|
context | Context | 是 | 应用的上下文。 FA模型的应用Context定义见Context。 Stage模型的应用Context定义见Context。 |
config | StoreConfig | 是 | 与此RDB存储相关的数据库配置。 |
callback | AsyncCallback<void> | 是 | 指定callback回调函数。 |
示例代码:
import { UIAbility } from '@kit.AbilityKit';
import { window } from '@kit.ArkUI';
import { BusinessError } from '@kit.BasicServicesKit';let store: relationalStore.RdbStore | undefined = undefined;class EntryAbility extends UIAbility {onWindowStageCreate(windowStage: window.WindowStage){const STORE_CONFIG: relationalStore.StoreConfig = {name: "RdbTest.db",securityLevel: relationalStore.SecurityLevel.S1};relationalStore.deleteRdbStore(this.context, STORE_CONFIG, (err: BusinessError) => {if (err) {console.error(`Delete RdbStore failed, code is ${err.code},message is ${err.message}`);return;}store = undefined;console.info('Delete RdbStore successfully.');})}
}
备份数据库
if (store !== undefined) {// "Backup.db"为备份数据库文件名,默认在RdbStore同路径下备份。也可指定路径:customDir + "backup.db"(store as relationalStore.RdbStore).backup("Backup.db", (err: BusinessError) => {if (err) {console.error(`Failed to backup RdbStore. Code:${err.code}, message:${err.message}`);return;}console.info(`Succeeded in backing up RdbStore.`);})
}
从备份数据库中恢复数据
if (store !== undefined) {(store as relationalStore.RdbStore).restore("Backup.db", (err: BusinessError) => {if (err) {console.error(`Failed to restore RdbStore. Code:${err.code}, message:${err.message}`);return;}console.info(`Succeeded in restoring RdbStore.`);})
}
关系型数据库开发实践
关系型数据库开发实践华为开发者学堂https://developer.huawei.com/consumer/cn/training/course/slightMooc/C101717498132814493