第5章
数据存储与访问
数据存储是开发应用程序时需要解决的最基本问题,虽然客户端App 的数据一般都由
云端(服务端)提供,但是随着移动互联网的发展,用户对应用程序的性能、体验等各方面要
求都有所增强,目前客户端App 一般都需要支持离线使用模式,因此在进行客户端应用程
序开发时需要客户端实现本地数据的存储与访问。本章结合具体案例介绍方舟开发框架提
供的JSAPI 实现本地存储与访问数据的机制,以便读者全面地了解本地数据存储与访问接
口,更好地开发HarmonyOS 应用程序。
5.概述
1
HarmonyOS 应用程序开发的数据管理机制包括轻量级数据存储(偏好文件)、文件、关扫一扫
系数据库、对象关系映射数据库、分布式数据服务和分布式文件服务等。华为官方推出的
JSAPI 提供了一系列完整的配套接口,用来实现HarmonyOS 应用程序开发中的数据存储
和访问机制。读者需要注意,JSAPI 中的部分数据存储与访问接口从APIversion6 开始
华为官方不再维护,所以推荐使用官方提供的最新接口开发HarmonyOS 应用程序。
5.1
轻量级数据存储与访问机制
1.
在HarmonyOS 应用程序开发中,轻量级数据存储以key-value结构的形式对数据进行
存取操作。数据存储形式为键值对,键(key)是不重复的关键字,它的类型为字符串型;值
(value)是数据值,它存储数据的类型包括数字型、字符型、布尔型。应用程序在获取某个轻
量级数据存储对象后,该存储对象中的数据将会被缓存在内存中,以便应用程序以更快的速
度实现数据访问,提高效率。当然,应用程序也可以将缓存的数据写入HarmonyOS 终端设
备存储器的文本文件中进行持久化存储。由于文件读写会产生不可避免的系统资源开销,
因此开发者在开发应用程序时,应尽量减少对存放在HarmonyOS 终端设备存储器中文本
文件的读写频率。轻量级数据存储访问机制适用于应用程序在本地存储少量数据,经常应
用于操作键值对形式数据的场景。从APIverin6 开始,JSAPI 提供的@oho.aa
sosdt.
storage接口可以实现数据存储对象的获取和写入。
1.文件存储与访问机制
5.2
文件通常应用于将数据以普通文件格式下载或保存到HarmonyOS 终端设备的本地存
储空间。从APIvesoJSAPI 提供的@ohsfli
rin6 开始,o.ieo接口可以实现对文件或目录进
行操作。但是,在操作文件或目录前,必须先通过Ability上下文提供的相关接口,获取操作
对象在内部存储目录或内部存储缓存目录的绝对路径,然后才能进行文件或目录的创建、打
开、读取、写入、复制、删除、重命名、修改操作权限、修改所有者等操作。
1.关系数据库存储与访问机制
5.3
关系数据库(RelationalDatabase,RDB)是一种基于关系模型管理数据的数据库。
HarmonyOS 关系数据库基于SQLite组件提供了一套完整的对本地数据库进行管理的机
制,对外提供了一系列的增、删、改、查等接口,也可以直接运行用户输入的SQL(Structured
QueryLanguage,结构化查询语言)语句来满足复杂的场景需要。SQLite是一款轻量级的
关系数据库管理系统,它既支持事务和批处理、自动版本管理、标准的CURD(Create、
Update、Retrieve、Delete)操作,也遵守ACID(Atomic、Consistency、Isolation、Durability)特
性。HarmonyOS 提供的关系数据库功能更加完善,查询效率更加高效,从APIversion7 开
始,JSAPI 提供的@oho.aar
sdt.db 接口可以实现关系数据的操作。
1.对象关系映射数据库存储与访问机制
5.4
对象关系映射(ObjectRelationalMapping,ORM)数据库是一款基于SQLite的数据库
框架,屏蔽了底层SQLite数据库的SQL 操作,针对实体和关系提供了增、删、改、查等一系
列的面向对象接口。在进行HarmonyOS 应用程序开发时,开发者不必再编写复杂的SQL
语句,而是直接以操作对象的形式操作数据库,所以在提升开发效率的同时,也能让开发者
聚焦于业务开发。对象关系映射数据库跟关系数据库一样,都使用SQLite作为持久化引
擎,底层使用的是同一套数据库连接池和数据库连接机制。对象关系映射数据库适用于开
发者使用的数据可以分解为一个或多个对象,且需要对数据进行增、删、改、查等操作,但是
不希望编写过于复杂的SQL 语句的场景。
5.睡眠质量测试系统的设计与实现
2
如今睡眠已经成为全世界人们共同关注的问题。由于长期睡眠质量不高,常会伴随着
多种疾病的产生,其中最突出的就是精神类疾病,睡眠障碍是它的主要表现形式。而大多数
人对睡眠认识不够,往往忽略了睡眠与身体健康的关系,这样就造成很多睡眠质量不高的人
错失了治疗的最佳时间,因此就需要提供一个方便快捷的方法来帮助这些人测量自己的睡
眠状况,让他们尽早得到相应的治疗和帮助。本节以国际公认的睡眠质量自测量表———阿
森斯失眠量表为理论依据,结合switch组件、stepper组件、stepper-item 组件、页面路由和
139
轻量级数据存储与访问机制设计并实现一个睡眠质量测试系统。
5.1
sich组件
2.wt
switch组件(开关选择器组件)用于开启或关闭某个功能,除支持通用属性和通用事件
外,还支持如表5.2所示的事件。扫一扫
1所示的属性和如表5.
表5.wth组件属性及功能
1
sic
属性名类型功能说明
checked boolean 设置开关是否选中,属性值包括false(默认值,未选中)和true
showtext boolean 设置开关是否显示文本,属性值包括false(默认值,不显示)和true
texton string 设置开关选中时显示的文本,默认值为On
textof
string 设置开关选中时显示的文本,默认值为Of
表5.h组件事件及功能
2
switc
change
事件名返回值功能说明
{checked:checkedValue} 开关选择器选中状态改变时,触发该回调事件
-witc1
所示。
【范例51】用sh组件在页面上实现一个模拟开灯、关灯的效果,运行效果如图5.
图5.开关选择器效果
1
1 40
css的代码如下。
1 .container {
2 display: flex;
3 flex-direction: column;
4 align-items: center;
5 margin: 15fp;
6 width: 100%;
7 height: 100%;
8 }
9 .switch-css {
10 texton-color: blue;
11 textoff-color: red;
12 font-size: 25fp;
13 }
上述第9~13行代码定义switch组件的样式,texton-color样式表示开关选择器处于
选中状态时显示的文本颜色,textoff-color样式表示开关选择器处于未选中状态时显示的
文本颜色。
hml的代码如下。
1
2
3
4
上述第2行代码用image组件加载代表灯亮的图片(light.png)和代表灯灭的图片
(black.png),这两张图片需要先复制到项目的common/images文件夹中。
js的代码如下。
1 export default {
2 data: {
3 imgSrc:'/common/images/black.png', //默认加载代表灯灭的图片
4 isChecked:false //默认开关选择器未选中
5 },
6 controlLamp(e){
7 if(e.checked){
8 this.imgSrc = '/common/images/light.png' //加载代表灯亮的图片
9 }else{
10 this.imgSrc = '/common/images/black.png' //加载代表灯灭的图片
11 }
12 }
13 }
上述第7~11行代码表示如果开关选择器处于选中状态,则加载代表灯亮的图片文件
(light.png),否则加载代表灯灭的图片文件(black.png)。
141
5.2
轻量级数据存储与访问接口
2.
轻量级数据存储为应用程序提供key-value(键值对)类型的文件数据处理能力,支持应
用程序对数据进行轻量级的存储及查询。数据存储形式为键值对,键的类型为字符串型,最
大长度为80B;值的存储数据类型包括数字型、字符型和布尔型,其中字符型值的最大长度
为8192B 。在HarmonyOS 应用程序开发中,借助JSAPI 提供的@ohsdatstoae接口
o.a.rg
可以实现数据存储对象的获取和写入,写入的数据保存在HarmonyOS 终端设备存储器的
文本文件中。
1.
读取指定文件
.dataStorae.etStoraenc(path:string):Storae,同步读取指定文件,并将数据
gggSygc参数及功能说明如表5.
g
加载到
etStoraSgteoSryangce
返回值类型及功能说明如表
类型的实例。getStorageSy5.
n4所示。
3所示。
扫一扫
表5.c参数及功能说明
3
getStorageSyn
参数名类型必填功能说明
path string 是设置应用程序内部数据存储路径
表5.c返回值类型及功能说明
4
getStorageSyn
返回值类型功能说明
返回Storage类型实例,可用于数据存储及查询操作
【范例5-2】用同步方式读取应用程序内部数据存储路径下的cofg.ni文件,并将
Storage
nii
cofg.ni文件的存储路径显示在页面上,运行效果如图5.
nii2所示。
图5.同步读取文件目录路径
2
1 42
hml的代码如下。
1
2 config.ini 文件的存储路径: {{ pathName }}
3
4
上述第1行代码引用的container样式类代码内容与范例5-1的container样式类代码
完全一样,限于篇幅,这里不再赘述。
js的代码如下。
1 import dataStorage from '@ohos.data.storage'
2 import featureAbility from '@ohos.ability.featureAbility'
3 export default {
4 data: {
5 pathName: " //保存config.ini 文件的存放目录
6 storage:" //保存数据存储实例
7 },
8 async openConfig() {
9 var context = featureAbility.getContext() //获取上下文
10 var path = await context.getFilesDir() //获得应用程序内部存储目录
11 this.storage = dataStorage.getStorageSync(path + '/config.ini')
//读取config.ini 文件
12 this.pathName = path
13 //操作config.ini 文件中的数据
14 }
15 }
HarmonyOS应用程序使用轻量级数据存储与访问机制存取数据时,必须首先从
@ohos.data.storage接口中导入dataStorage包,即上述第1行代码;然后引用该包中的各
种方法对轻量级数据进行操作。轻量级数据存储与访问实际上就是对内部存储器上以键值
对格式存储的文本文件进行操作,所以在读取文件时必须指明文件的存放位置,即上述第
2行及9~10行代码,其中第2行代码表示从@ohos.ability.featureAbility接口中导入
featureAbility包,第9~10行代码表示调用该包中的getContext()方法获得Ability上下
文;再通过Ability上下文调用getFilesDir()方法异步获取应用程序在内部存储器上的文件
路径。由于getFilesDir()方法是异步(async)执行的,所以上述第8~14行代码定义了一个
异步事件,其中第10行代码中的await表示只有在获得应用程序内部存储目录后,才能执
行第11行及后面的代码。虽然异步事件会返回一个Promise对象,但代码前用await关键
字表示可以等待异步事件的返回值,也就是说,await不仅可以用于等待返回Promise对象,
而且它还可以等待任意表达式的结果,所以上述第10行代码直接将返回的值赋给path变
量。从图5.2可以看出,getFilesDir()方法返回的应用程序在内部存储器上的文件路径为
“/data/data/应用程序包名/files”。如果将上述第10行代码修改为下述代码,则表示获取
应用程序内部存储器上的缓存目录路径,运行效果如图5.3所示。getCacheDir()方法返回
1 43
的应用程序在内部存储器上的缓存目录路径为“/data/data/应用程序包名/cache”。
图5.3 同步读取缓存目录路径
1 var path = await context.getCacheDir() //获得应用程序内部存储缓存目录
.dataStorage.getStorage(path:string,callback:AsyncCallback):void,
异步读取指定文件,并将数据加载到Storage类型的实例,以callback形式返回结
果。getStorage参数及功能说明如表5.5所示。
表5.5 getStorage参数及功能说明
参数名类 型必填功能说明
path string 是设置应用程序内部数据存储路径
callback AsyncCallback 是回调函数
例如,要实现范例5-2的功能,也可以将范例5-2的第11~13行js代码修改为如下
代码。
1 var that = this
2 dataStorage.getStorage(path + '/config.ini', function (err, storage) {
3 if (err) {
4 that.pathName ="读内部存储文件失败"
扫一扫
1 44
5 return;
6 }
7 //用storage 实例操作config.ini 文件中的数据
8 that.pathName = path
9 })
. dataStorage.getStorage(path:string):Promise,异步读取指定文件,并
将数据加载到Storage 实例。getStorage 参数及功能说明如表5.3 所示。
getStorage返回值类型及功能说明如表5.6所示。
表5.6 getStorage返回值类型及功能说明
返回值类型功能说明
Promise 返回Promise实例,用于异步获取结果
例如,要实现范例5-2的功能,也可以将范例5-2的第11~13行js代码修改为如下
代码。
1 var that = this
2 let promise = dataStorage.getStorage(path + '/config.ini')
3 promise.then((storage) => {
4 //用storage 实例操作config.ini 文件中的数据
5 that.pathName = path
6 }).catch((err) => {
7 that.pathName = "读内部存储文件失败"
8 })
2.向指定存储对象写数据
. putSync(key:string,value:ValueType):void,同步将数据写入Storage类型的实
例,并用flush()或flushSync()方法将Storage类型的实例写入指定文件保存。
putSync参数及功能说明如表5.7所示。
表5.7 putSync参数及功能说明
参数名类 型必填功能说明
key string 是设置要存储或修改的键,不能为空
value number、string或boolean 是设置要存储或修改的值
【范例5-3】 用同步方式将登录用户名(key为loginName,value为nipaopao)和登录
密码(key为loginPwd,value为123456)以键值对方式保存在应用程序内部存储路径下的
config.ini文件中。
在实现范例5-2的基础上,在hml的代码中增加1个“保存数据”按钮,其代码如下。
1
扫一扫
1 45
在实现范例5-2的基础上,在js的代码中增加1个“保存数据”单击事件的回调方法,其
代码如下。
1 writeConfig() {
2 this.storage.putSync('loginName', 'nipaopao')
//key 为'loginName',value 为'nipaopao'
3 this.storage.putSync('loginPwd', '123456')
//key 为'loginPwd',value 为'123456'
4 this.storage.flushSync() / /保 存 到 文 件 中
5 console.info("保存成功")
6 }
. put(key:string,value:ValueType,callback:AsyncCallback):void,异
步将数据写入Storage类型的实例,并用flush()或flushSync()方法将Storage类型
的实例写入指定文件保存。put参数及功能说明如表5.8所示。
表5.8 put参数及功能说明
参数名类 型必填功能说明
key string 是设置要存储或修改的键,不能为空
value number、string或boolean 是设置要存储或修改的值
callback AsyncCallback 是回调函数
例如,要实现范例5-3的功能,也可以将“保存数据”单击事件的回调方法修改为如下
代码。
1 writeConfig(){
2 var that = this
3 this.storage.put('loginName', 'nipaopao', function (err) {
//保存登录用户名
4 if (err) {
5 console.info("保存失败:" + err)
6 return
7 }
8 that.storage.flushSync()
9 console.info("保存成功")
10 })
11 //保存登录密码的代码类似,此处略
12 }
. put(key:string,value:ValueType):Promise,异步将数据写入Storage
类型的实例,并用flush()或flushSync()方法将Storage类型的实例写入指定文件
保存。put参数及功能说明如表5.8所示。put返回值类型及功能说明如表5.9
所示。
扫一扫
1 46
表5.9 put返回值类型及功能说明
返回值类型功能说明
Promise 返回Promise实例,用于异步处理
例如,要实现范例5-3的功能,也可以将“保存数据”单击事件的回调方法修改为如下代码。
1 writeConfig() {
2 let promise = this.storage.put('loginName', 'nipaopao')
3 promise.then(() => {
4 console.info("保存成功")
5 }).catch((err) => {
6 console.info("保存失败:" + err)
7 })
8 //保存登录密码的代码类似,此处略
9 }
3.从指定存储对象中读数据
. getSync(key:string,defValue:ValueType):ValueType,同步获取指定键的值,如果值
为null或者非默认值类型,则返回默认数据。getSync参数及功能说明如表5.10所示。
表5.10 getSync参数及功能说明
参数名类 型必填功能说明
key string 是设置要获取的键,不能为空
defValue number、string或boolean 是若给定的键不存在,则设置该键返回的默认值
【范例5-4】 用同步方式从应用程序内部存储路径下的config.ini文件中读出登录用户名
(key为loginName)和登录密码(key为loginPwd),并显示在如图5.4所示页面的对应位置。
图5.4 同步读出轻量级数据
扫一扫