OpenHarmony之eTS DataAbility 的使用及数据管理

会挽雕弓如满月,西北望,射天狼。这篇文章主要讲述OpenHarmony之eTS DataAbility 的使用及数据管理相关的知识,希望能为你提供帮助。
OpenHarmony之eTS DataAbility 的使用及数据管理@toc
1.介绍本文是eTS DataAbility样例实践,主要展示了eTS FA使用 eTS DataAbility实现图书信息的管理功能,包括 rdb数据库的创建,数据的增删改查,批量操作等。是继 ServiceAbility 的第二篇。
Ability是HarmonyOS应用程序的重要组成部分,分为FA(Feature Ability)和PA(Particle Ability)两种类型。PA有 Service Ability和Data Ability,Service Ability模板用于提供后台运行任务的能力;Data Ability模板用于对外部提供统一的数据访问抽象。
Gitee 样例地址
https://gitee.com/openharmony/app_samples/tree/master/ability/DataAbility
大家也可以自行下载运行,但需要OpenHarmony的设备才能运行。
< br>
先来展示一下效果

OpenHarmony之eTS DataAbility 的使用及数据管理

文章图片

2.代码讲解项目结构图
└─main │config.json │ ├─ets │├─DataAbility ││data.ts ││ │└─MainAbility ││app.ets ││ │├─component ││bookView.ets ││searchBar.ets ││titleBar.ets ││ │├─model ││BookDataModel.ts ││DaHelperConst.ts ││ │└─pages │index.ets │query.ets │update.ets │ └─resources

2.1 PA端 DataAbility
1). data.ts 数据访问能力类创建一个DataAbility很简单,就是File---New ----Ability---DataAbility,起个名字,
你可以按照数据类型命名,例如:GoodsDataAbility一个用来存储商品的DataAbility,需要注意的是,你命名的其实是个目录或者叫做路径,这个路径指向一个叫data.ts的文件,相应的代码编写也是在这个data.ts的文件。
一起来看一下实现一个DataAbility都需要做哪些事,
引入依赖
//引入数据访问类 import dataAbility from @ohos.data.dataAbility //引入rdb库 import dataRdb from @ohos.data.rdb

定义rdb库对象、库配置、表名、创表SQL等变量
//rdb库对象 let rdbStore: dataRdb.RdbStore = undefined //库的配置信息:库名称 const STORE_CONFIG =name: book.db //表名 const TABLE_NAME = book //表结构 const SQL_CREATE_TABLE = CREATE TABLE IF NOT EXISTS book(id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL, introduction TEXT NOT NULL)

接下来是功能函数的实现,这部分完全可以直接复用。
初始化库和表
//初始化库和表 onInitialized(abilityInfo) console.info(`$TAG DataAbility onInitialized`) console.log(`$TAG create table begin`) dataRdb.getRdbStore(abilityInfo, STORE_CONFIG, 1) .then((rdb) => console.log(`$TAG create table done`) rdb.executeSql(SQL_CREATE_TABLE) rdbStore = rdb console.log(`$TAG create table end`) ) .catch((error) => console.log(`$TAG create table err = $JSON.stringify(err)`)) ,

增删改查 数据操作
//增删改查 数据操作 insert(uri, valueBucket, callback) console.info(TAG +insert start) rdbStore.insert(TABLE_NAME, valueBucket, callback) , batchInsert(uri, valueBuckets, callback) console.info(TAG +batch insert start) for (let i = 0; i < valueBuckets.length; i++) console.info(TAG +batch insert i= + i) if (i < valueBuckets.length - 1) rdbStore.insert(TABLE_NAME, valueBuckets[i], (err: any, num: number) => console.info(TAG +batch insert ret= + num) ) else rdbStore.insert(TABLE_NAME, valueBuckets[i], callback), query(uri, columns, predicates, callback) console.info(TAG +query start) let rdbPredicates = dataAbility.createRdbPredicates(TABLE_NAME, predicates) rdbStore.query(rdbPredicates, columns, callback) , update(uri, valueBucket, predicates, callback) console.info(TAG + update start) let rdbPredicates = dataAbility.createRdbPredicates(TABLE_NAME, predicates) rdbStore.update(valueBucket, rdbPredicates, callback) , delete(uri, predicates, callback) console.info(TAG + delete start) let rdbPredicates = dataAbility.createRdbPredicates(TABLE_NAME, predicates) rdbStore.delete(rdbPredicates, callback)

2.2 FA端 MainAbility
1).model下的BookDataModel.ts 模型创建一个BookModel 数据模型,定义一些属性字段 ,一个编号、一个名称、一个介绍。
export class BookModel id: number name: string introduction: stringconstructor(id: number, name: string, introduction: string) this.id = id this.name = name this.introduction = introduction

还是在这个ts文件中,再编写一些方便展示的初始化测试数据的函数,export出去就可以直接调用了。这个地方需要注意的是自增ID不要写 。
//初始化测试数据 export function initValuesBuckets() let valuesBuckets = [ name: Book name1, introduction: Book introduction1 , name: Book name2, introduction: Book introduction2 , name: Book name3, introduction: Book introduction3 ] return valuesBuckets

再编写一个将resultSet数据转换位BookModel 数组的函数,用于处理DA_HELPER返回的数据。
//获取一个BookModel 的数据列表 export function getListFromResultSet(resultSet) console.info(TAG +getListFromResultSet) let bookList = [] console.log(TAG +resultSet column names: + resultSet.columnNames) console.log(TAG +resultSet row count: + resultSet.rowCount) console.log(TAG +resultSet goToFirstRow: + resultSet.goToFirstRow()) for (let i = 0; i < resultSet.rowCount; i++) //按照构造函数进行封装 let book = new BookModel( resultSet.getDouble(resultSet.getColumnIndex(id)) , resultSet.getString(resultSet.getColumnIndex(name)) , resultSet.getString(resultSet.getColumnIndex(introduction)))//添加到列表中 bookList.push(book)console.log(TAG +resultSet book: + JSON.stringify(book)) console.log(TAG +resultSet goToNextRow: + resultSet.goToNextRow())return bookList

2).model下的DaHelperConst.ts常量类定义一个DaHelperConst.ts常量类,用于存储数据库常用属性。
首先引入FA访问类
//引入FA访问类 import featureAbility from @ohos.ability.featureAbility

定义数据访问URI、表列名、DataAbility帮助类 等常量
//定义 数据访问URI 常量 export const BASE_URI = dataability:///ohos.samples.etsdataability.DataAbility //定义 表的列名 export const COLUMNS = [id, name, introduction]//获取一个DataAbility的帮助类 export const DA_HELPER = featureAbility.acquireDataAbilityHelper(BASE_URI)

3).component下的bookView.ets视图组件,实现了一个图书展示的列表效果。
//引入 BookDataModel 数据模块 importBookModelfrom ../model/BookDataModel

定义 book数据模型对象、删除数据的回调函数
@Component export struct BookView //定义 book数据模型对象 private book: BookModel = null //定义 删除数据的回调函数 private deleteCallback = null

构建视图显示
build() Row() //一张图片 Image($r(app.media.book)) .height(110).width(80) .objectFit(ImageFit.Cover) .margin( top: 5, bottom: 5 )//垂直方向的两行文本 Flex( direction: FlexDirection.Column, alignItems: ItemAlign.Start ) Text(this.book.name) .fontColor(Color.Black) .fontSize(22) .fontWeight(FontWeight.Bold) Text(this.book.introduction) .fontColor(Color.Grey) .fontSize(20) .margin( top: 10 ).layoutWeight(1) .margin( left: 5 )//删除数据的按钮 if (this.deleteCallback !== null) Button() Image($r(app.media.delete_red)) .height(35).width(35) .objectFit(ImageFit.Contain).type(ButtonType.Circle) .height(50).width(50) .backgroundColor(#F5F5F5) .onClick(() => this.deleteCallback(this.book) ).width(100%) .padding( left: 15, right: 15 )

效果图
OpenHarmony之eTS DataAbility 的使用及数据管理

文章图片

4).component下的searchBar.ets视图组件,实现了一个搜索栏的效果,使用了Stack 布局,让放大镜能叠加在文本输入框上。
用Text 模拟TextInput 效果,点击进行跳转到搜索界面。
//引用路由,用于跳转界面 import router from @ohos.router@Preview @Component export struct SearchBar build() Stack( alignContent: Alignment.End ) //模拟TextInput的文本 Text($r(app.string.search_tip)) .height(80%).width(94%) .fontSize(16) .padding( left: 15 ) .margin(3%) .backgroundColor(#A5A5A5) .border( radius: 20 )//放大镜icon Image($r(app.media.search_gray)) .height(40).width(40) .margin( right: 5% ) .objectFit(ImageFit.Contain).height(50).width(100%) .backgroundColor(#F5F5F5) .onClick(() => router.push( url: pages/Query ) )

效果图
OpenHarmony之eTS DataAbility 的使用及数据管理

文章图片

5).component下的titleBar.ets视图组件,实现了一个顶部标题栏的效果,提供了一个批量插入数据的操作按钮。
组件内定义回调函数的声明,在具体使用组件的界面在对回调函数进行实现,可以学习这种设计组件的方法。
@Component export struct TitleBar //定义 批量插入的回调函数 private batchInsertCallback = nullbuild() Row() //标题名称 Text($r(app.string.title)) .fontColor(Color.White) .fontSize(20) .layoutWeight(1)//批量插入 操作按钮 Button() Text($r(app.string.batch_insert)) .fontColor(Color.White) .fontSize(22) .textAlign(TextAlign.End).type(ButtonType.Normal) .height(100%) .backgroundColor(#0D9FFB) .onClick(() => this.batchInsertCallback() ).height(8%).width(100%) .backgroundColor(#0D9FFB) .padding( left: 15, right: 15 )

6).page下的index.etsindex.ets是和用户完成交互的主要页面。
需要引入数据访问能力类、路由,前面定义的常量类、视图组件、数据模块类等。
//引入数据访问能力类 import dataAbility from @ohos.data.dataAbility //引入路由,实现跳转界面 import router from @ohos.router//引入定义的常量、视图组件 importBASE_URI, COLUMNS, DA_HELPERfrom ../model/DaHelperConst importBookViewfrom ../component/BookView importTitleBarfrom ../component/TitleBar importSearchBarfrom ../component/SearchBar//引入数据模块类 importBookModel, initValuesBuckets, getListFromResultSetfrom ../model/BookDataModel

通过DA_HELPER查询数据实现页面显示图书列表效果,实现删除和批量插入数据的效果。
@Entry @Component struct Index @State bookList: Array< BookModel> = []//生命周期回调,自动执行,页面显示前 //页面显示时触发一次,包括路由过程、应用进入前后台等场景,仅@Entry修饰的自定义组件生效。 onPageShow() this.queryAll()queryAll = () => console.info(TAG +queryAll) //获取谓词 let predicates = new dataAbility.DataAbilityPredicates() //使用DA_HELPER 查询数据 DA_HELPER.query(BASE_URI, COLUMNS, predicates, (err, resultSet) => //重新封装查询结果 this.bookList = getListFromResultSet(resultSet) )deleteCallback = (book) => let predicates = new dataAbility.DataAbilityPredicates() predicates.equalTo(id, book.id) //使用DA_HELPER 删除数据 DA_HELPER.delete(BASE_URI, predicates, (err, num) => console.info(TAG +delete num= + num) this.queryAll() )batchInsertCallback = () => let valuesBuckets = initValuesBuckets() //使用DA_HELPER 批量插入数据 DA_HELPER.batchInsert(BASE_URI, valuesBuckets, (err, num) => console.info(TAG +batch insert num= + num) this.queryAll() )

build代码块,实现了列表显示的效果,使用了Stack布局,List等组件
点击行,跳转到更新数据界面,传递book对象过去,注意跳转的路由要在config.json配置好。
build() Column() //标题栏 TitleBar( batchInsertCallback: this.batchInsertCallback ) //搜索栏 SearchBar() //列表 Stack( alignContent: Alignment.BottomEnd ) //列表显示 List() ForEach(this.bookList, item => ListItem() BookView( book: item, deleteCallback: this.deleteCallback ).onClick(() => //点击行,跳转到更新数据界面,传递book对象过去 router.push( url: pages/Update, params:book: item) ) , item => JSON.stringify(item)).width(100%) .margin( bottom: 100 ) .constraintSize( minHeight: 100% ) .divider( strokeWidth: 1, color: Color.Gray, startMargin: 10, endMargin: 10 )//添加单条数据按钮 Button() Image($r(app.media.add)).type(ButtonType.Circle) .width(60) .height(60) .backgroundColor(#0D9FFB) .margin( bottom: 150, right: 50 ) .onClick(() => console.info(TAG +insert onClick) let valuesBuckets =name: Book name, introduction: Book introduction DA_HELPER.insert(BASE_URI, valuesBuckets, (err, num) => console.info(TAG +insert num= + num) this.bookList.push( id: num, name: Book name, introduction: Book introduction ) ) ).width(100%).height(100%).width(100%).height(100%)

效果图
OpenHarmony之eTS DataAbility 的使用及数据管理

文章图片

7).page下的query.ets引入依赖和index.ets类似
import router from @ohos.router; import dataAbility from @ohos.data.dataAbility importBASE_URI, COLUMNS, DA_HELPERfrom ../model/DaHelperConst importBookModel, getListFromResultSetfrom ../model/BookDataModel importBookViewfrom ../component/BookView

查询数据
//查询数据 query(queryStr) let predicates = new dataAbility.DataAbilityPredicates()//根据名字或介绍模糊匹配 predicates.contains(name, queryStr) .or() .contains(introduction, queryStr) DA_HELPER.query(BASE_URI, COLUMNS, predicates, (err, resultSet) => this.bookList = getListFromResultSet(resultSet) )

列表显示,和index.ets 类似,没有了删除按钮。
使用了ForEach、Stack、 TextInput 等组件, TextInput组件的onChange事件触发查询。
build() Column() Row() Image($r(app.media.ic_back)) .width(40).height(40) .objectFit(ImageFit.Contain) .onClick(() => router.back() ) Text($r(app.string.title)) .fontColor(Color.White) .fontSize(20) .layoutWeight(1).height(50).width(100%) .backgroundColor(#0D9FFB) .padding( left: 10, right: 10 )Stack( alignContent: Alignment.End ) TextInput( placeholder: $r(app.string.search_placeholder)) .height(85%).width(94%) .padding( left: 15 ) .margin(3%) .backgroundColor(#F0F0F0) .border( radius: 20 ) //触发查询 .onChange((value: string) => console.info(TAG +query str= + value) if (value !== ) this.query(value) else this.bookList = []) Image($r(app.media.search_gray)) .height(40).width(40) .margin( right: 5% ) .objectFit(ImageFit.Contain).width(100%).height(50) .backgroundColor(#F5F5F5)List() ForEach(this.bookList, item => ListItem() BookView( book: item, deleteCallback: null ).onClick(() => router.push( url: pages/update, params:book: item) ) , item => JSON.stringify(item)).width(100%) .layoutWeight(1) .divider( strokeWidth: 1, color: Color.Gray, startMargin: 10, endMargin: 10 )

OpenHarmony之eTS DataAbility 的使用及数据管理

文章图片

8).page下的update.ets引入依赖
//引入依赖 import router from @ohos.router; import prompt from @system.prompt; import dataAbility from @ohos.data.dataAbilityimportBASE_URI, DA_HELPERfrom ../model/DaHelperConst importBookModelfrom ../model/BookDataModel

声明BookModel的变量,从router中接收携带的参数book对象,用于原信息的显示
@Entry @Component struct Update //从router中接收携带的参数book对象,用于原信息的显示 private book: BookModel = < BookModel> router.getParams()["book"]

使用DA_HELPER 更新数据,更新完返回列表界面。
updateBook = () => let predicates = new dataAbility.DataAbilityPredicates() predicates.equalTo(id, this.book.id) let valuesBucket = name: this.book.name, introduction: this.book.introductionDA_HELPER.update(BASE_URI, valuesBucket, predicates, (err, num) => console.info(TAG +update book num= + num) router.back() )

显示要修改的图书信息,支持修改,支持返回、提交修改按钮。
使用了Scroll、Image、Text、TextInput等组件。
build() Column() Row() //返回按钮 Image($r(app.media.ic_back)) .width(40).height(40) .objectFit(ImageFit.Contain) .onClick(() => router.back() )//标题 Text($r(app.string.title)) .fontColor(Color.White) .fontSize(20) .layoutWeight(1) //提交修改按钮 Image($r(app.media.submit)) .width(50).height(50) .objectFit(ImageFit.Contain) .onClick(() => console.info(TAG +update onClick,title= + this.book.name) if (this.book.name ===|| this.book.introduction === ) prompt.showToast( message: Please input name or introduction ) returnthis.updateBook() ).height(50).width(100%) .backgroundColor(#0D9FFB) .padding( left: 10, right: 10 )//显示要修改的信息,支持滚动条 Scroll() Column() Image($r(app.media.book)) .width(120).height(150) .objectFit(ImageFit.Fill) .margin(5) Text($r(app.string.book_name)) .fontWeight(FontWeight.Bold) .fontSize(22) .width(100%) .margin( top: 20 ) .fontColor(Color.Black) TextInput( placeholder: input name, text: this.book.name ) .type(InputType.Normal) .placeholderColor(Color.Gray) .fontSize(19) .margin( top: 10 ) //修改信息后更新book对象 .onChange((value: string) => this.book.name = value )Text($r(app.string.book_intro)) .fontWeight(FontWeight.Bold) .fontSize(22) .width(100%) .fontColor(Color.Black) .margin( top: 20 ) TextInput( placeholder: input introduction, text: this.book.introduction ) .type(InputType.Normal) .placeholderColor(Color.Gray) .fontSize(19) .margin( right: 10, top: 10 ) //修改信息后更新book对象 .onChange((value: string) => this.book.introduction = value ).width(100%) .constraintSize( minHeight: 100% ) .padding(15) .height(100%)

3.补充说明1.我们发现并没有调用 DataAbility 的代码,那DataAbility 怎么被跑起来的呢?
其实是 DataAbility 是会被自动运行的,只要在config.json 中做了配置,当应用启动后,DataAbility就会被自动运行,在DataAbility完成初始化后,会调用声明周期回调函数 onInitialized,完成数据库的初始化。
【OpenHarmony之eTS DataAbility 的使用及数据管理】看一下 DataAbility 在config.json 中的配置
"abilities": ["visible": true, "srcPath": "DataAbility", "name": ".DataAbility", "icon": "$media:icon", "srcLanguage": "ets", "description": "$string:description_dataability", "type": "data", "uri": "dataability://ohos.samples.etsdataability.DataAbility"

启动应用,从日志输出中我们可以看到 DataAbility 被运行。
05-17 23:00:11.016 526-1367/foundation I 01110/AppMgrService: [module_running_record.cpp(LaunchAbility:178)]ScheduleLaunchAbility ability:ohos.samples.etsdataability.DataAbility

那DataAbility 数据的增删改查,也没有看到调用的代码呢?
代码里只是用了DA_HELPER对象来操作数据,并没有调用DataAbility/data.ts 的 insert/batchInsert/query/update/delete 这些函数,
其实是 DA_HELPER 在初始化时 绑定的 BASE_URI(如下)和 config.json文件中 DataAbility 的uri 是一致的,可以看上面config.json 的配置中uri的值。
(注意 config.json中的 uri 只能是 " dataablity://xxxxxxxxx" ,两道杠 )。
//定义 数据访问URI 常量 export const BASE_URI = dataability:///ohos.samples.etsdataability.DataAbility //获取一个DataAbility的帮助类 export const DA_HELPER = featureAbility.acquireDataAbilityHelper(BASE_URI)

有关BASE_URI格式说明参见下图,更详尽的参考
OpenHarmony之eTS DataAbility 的使用及数据管理

文章图片

2.DataAbility/data.ts 中创表语句中的表名,注意要和TABLE_NAME常量保持一致,否则数据无法插入成功。
< br>
最后,
我们可以在这个基础上去扩展库、扩展表,去实现我们自己应用的数据管理。
附件链接:https://ost.51cto.com/resource/1975
想了解更多关于开源的内容,请访问:
51CTO 开源基础软件社区
https://ost.51cto.com/#bkwz

    推荐阅读