HarmonyOS NEXT:保存应用数据

news/2025/2/6 7:26:01/

用户首选项使用

用户首选项的特点

数据体积小、访问频率高、有加载速度要求的数据如用户偏好设置、用户字体大小、应用的配置参数。

用户搜选项(Preferences)提供了轻量级配置数据的持久化能力,支持订阅数据变化的通知能力。不支持分布式同步。

基于Key-Value的数据结构,Key是不重复的关键字,Value是数据值。

Preferences是一种非关系型数据库,不遵循数据库的ACID特性,数据见毫无关系。

用户首选项存储在内存中,存储数据量过大会导致应用占用内存过多。如果需要持久化存储,可以调用Flush接口。

不支持数据加密。

用户首选项使用场景

应用配置参数、用户偏好设置,如应用字体大小个性化调整、主题颜色等。

用户首选项机制原理

用户首选项实际通过持久化文件的形式存储在应用沙箱目录中,ArkTS提供交互接口。每个持久化文件唯一关联一个实例。

用户程序通过UIAbilityContext来获得Preferences实例。 因为一个程序可以有多个UIAbility,所以可以获得多个Preferences实例。

用户首选项主要API

preferences.getPreferencesSync10+

getPreferencesSync(context: Context, options: Options): Preferences

获取Preferences实例,此为同步接口。

参数:

参数名类型必填说明
contextContext

应用上下文。

FA模型的应用Context定义见Context。

Stage模型的应用Context定义见Context。

optionsOptions与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实例持久化,此为同步接口。

参数:

参数名类型必填说明
keystring要修改的存储的Key,不能为空。
valueValueType存储的新值。

示例代码: 

dataPreferences.putSync('startup', 'auto');
// 当字符串有特殊字符时,需要将字符串转为Uint8Array类型再存储
let uInt8Array1 = new util.TextEncoder().encodeInto("~!@#¥%……&*()——+?");
dataPreferences.putSync('uInt8', uInt8Array1);
hasSync10+

hasSync(key: string): boolean

检查缓存的Preferences实例中是否包含名为给定Key的存储键值对,此为同步接口。

参数:

参数名类型必填说明
keystring要检查的存储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,此为同步接口。

参数:

参数名类型必填说明
keystring要获取的存储Key名称,不能为空。
defValueValueType默认返回值。

返回值:

类型说明
ValueType返回键对应的值。

示例代码: 

let value: preferences.ValueType = dataPreferences.getSync('startup', 'default');
deleteSync10+

deleteSync(key: string): void

从缓存的Preferences实例中删除名为给定Key的存储键值对,可通过flush将Preferences实例持久化,此为同步接口。

参数:

参数名类型必填说明
keystring要删除的存储key名称,不能为空。

示例代码: 

dataPreferences.deleteSync('startup');
flush

flush(callback: AsyncCallback<void>): void

将缓存的Preferences实例中的数据异步存储到用户首选项的持久化文件中,使用callback异步回调。

参数:

参数名类型必填说明
callbackAsyncCallback<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后需要重新订阅数据变更。

参数:

参数名类型必填说明
typestring事件类型,固定值'change',表示数据变更。
callbackCallback<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回调。

参数:

参数名类型必填说明
typestring事件类型,固定值'dataChange',表示精确的数据变更。
keysArray<string>需要订阅的key集合。
callbackCallback<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

取消订阅数据变更。

参数:

参数名类型必填说明
typestring事件类型,固定值'change',表示数据变更。
callbackCallback<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其他接口并发调用。

参数:

参数名类型必填说明
contextContext

应用上下文。

FA模型的应用Context定义见Context。

Stage模型的应用Context定义见Context。

optionsOptions与Preferences实例相关的配置选项。
callbackAsyncCallback<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目前不支持多线程并发操作。

参数:

参数名类型必填说明
contextContext

应用的上下文。

FA模型的应用Context定义见Context。

Stage模型的应用Context定义见Context。

configStoreConfig与此RDB存储相关的数据库配置。
callbackAsyncCallback<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等接口代替。

不支持分号分隔的多条语句。

参数:

参数名类型必填说明
sqlstring指定要执行的SQL语句。
callbackAsyncCallback<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,否则会查询失败。

参数:

参数名类型必填说明
tablestring指定的目标表名。
valuesValuesBucket表示要插入到表中的数据行。
callbackAsyncCallback<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,否则会查询失败。

参数:

参数名类型必填说明
valuesValuesBucketvalues指示数据库中要更新的数据行。键值对与数据库表的列名相关联。
predicatesRdbPredicatesRdbPredicates的实例对象指定的更新条件。
callbackAsyncCallback<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异步回调。

参数:

参数名类型必填说明
predicatesRdbPredicatesRdbPredicates的实例对象指定的删除条件。
callbackAsyncCallback<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,否则会查询失败。

参数:

参数名类型必填说明
predicatesRdbPredicatesRdbPredicates的实例对象指定的查询条件。
callbackAsyncCallback<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中配置了自定义路径,则必须调用此接口进行删库。 

参数:

参数名类型必填说明
contextContext

应用的上下文。

FA模型的应用Context定义见Context。

Stage模型的应用Context定义见Context。

configStoreConfig与此RDB存储相关的数据库配置。
callbackAsyncCallback<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 


http://www.ppmy.cn/news/1569740.html

相关文章

实验十四 EL和JSTL

实验十四 EL和JSTL 一、实验目的 1、掌握EL表达式的使用 2、掌握JSTL的使用 二、实验过程 1、在数据库Book中建立表Tbook&#xff0c;包含图书ID&#xff0c;图书名称&#xff0c;图书价格。实现在bookQuery.jsp页面中模糊查询图书&#xff0c;如果图书的价格在50元以上&#…

vscode+vue3+高得地图开发过过程中本地视频及地图json文件的发布问题

很久没发blog了&#xff0c;最近vscodevue3高得地图开发中&#xff0c;因为有开发的视频教程&#xff0c;还有地图的边界的.json文件&#xff0c;这些静态文件发布时&#xff0c;如果处理不当&#xff0c;build命令会将这些静态文件进行打包。打包后文件名变化了&#xff0c;这…

DeepSeek的出现对全球GPT产业产生的冲击

引言 近年来&#xff0c;人工智能技术的迅猛发展推动了自然语言处理&#xff08;NLP&#xff09;领域的革命性进步。特别是以GPT&#xff08;Generative Pre-trained Transformer&#xff09;系列模型为代表的大规模预训练语言模型&#xff0c;已经在全球范围内引发了广泛关注…

python编程-文件和目录操作,字符串操作

python的文件和目录操作主要用到os包。最常用的接口如下&#xff1a; 1. 获取当前工作目录 import os current_dir os.getcwd() print("当前目录:", current_dir) # 输出: /Users/your/path 2. 切换工作目录 os.chdir("/tmp") # 切换到 /tmp 目录 p…

利用TensorFlow.js实现浏览器端机器学习:一个全面指南

引言 随着深度学习技术的不断发展&#xff0c;机器学习已从传统的服务器端运算逐渐转向了前端技术。TensorFlow.js 是 Google 推出的一个用于在浏览器中进行机器学习的开源库&#xff0c;它允许开发者在浏览器中直接运行机器学习模型&#xff0c;而无需依赖后端服务器。Tensor…

使用图形化界面和终端配置防火墙安全策略

一、项目简介 防火墙想必大家都很熟悉&#xff0c;电脑自带的防护墙我们都使用过&#xff0c;今天我们进行对企业防火墙USG6000V1这款防火墙使用Web图形化界面和控制终端进行防火墙的安全策略的配置。 二、详细概述 2.1 图谱图的搭建 使用Web图形化的界面和控制台终端来对该防…

C#Halcon差异分类模型

缺陷检测抛开blob分析&#xff0c;尺寸判定与深度学习之外还有一种常用的方式&#xff0c;个人称之为差异分类模型&#xff0c;简称差分模型 个人对其应用过程为&#xff1a; 准备阶段&#xff1a;图像预处理&#xff0c;创建模型&#xff0c;查找模型定位&#xff0c;创建差…

CSS的媒体查询语法

CSS的媒体查询语法 常见的媒体类型常见的特性示例 CSS的媒体查询语法可以根据不同的设备特性&#xff08;如屏幕尺寸、分辨率等&#xff09;应用不同的样式。基本语法如下&#xff1a; media 媒体类型 and (特性: 值) {/* 样式规则 */ }常见的媒体类型 screen&#xff1a;用于…