#跟着坚果学鸿蒙# HarmonyOS 5 DataAbility组件概述:数据共享与跨应用通信
·
一、DataAbility基本概念
HarmonyOS 5中的DataAbility是一种特殊类型的Ability,主要用于提供统一的数据访问接口,实现应用间的数据共享。与UIAbility不同,DataAbility不直接与用户交互,而是专注于数据操作,为其他应用提供标准化的数据访问能力。
DataAbility的核心特点包括:
- 标准化接口:提供CRUD(创建、读取、更新、删除)等标准数据操作接口
- 跨进程通信:通过URI标识数据资源,支持跨应用访问
- 安全控制:通过权限机制保护敏感数据
- 多种数据源支持:可以封装SQLite数据库、文件系统等多种数据存储方式
二、DataAbility工作原理
DataAbility基于客户端-服务器模式工作:
- 服务端:实现DataAbility的子类,重写数据操作方法
- 客户端:通过DataAbilityHelper访问服务端提供的数据
通信过程使用URI标识数据资源,格式通常为:dataability:///[authority]/[path]?[query]
三、完整示例:构建联系人DataAbility
下面我们实现一个完整的联系人管理DataAbility示例,包含服务端和客户端代码。
1. DataAbility服务端实现
首先创建ContactDataAbility.ts
文件:
// ContactDataAbility.ts
import dataAbility from '@ohos.ability.dataAbility'
import relationalStore from '@ohos.data.relationalStore'
const CONTACTS_TABLE = 'contacts'
const DB_NAME = 'contact_db'
const STORE_CONFIG = {
name: DB_NAME,
securityLevel: relationalStore.SecurityLevel.S1
}
export default class ContactDataAbility extends dataAbility.DataAbility {
private rdbStore: relationalStore.RdbStore | null = null
// 初始化数据库
async onInitialized(): Promise<void> {
try {
const sql = `CREATE TABLE IF NOT EXISTS ${CONTACTS_TABLE} (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL,
phone TEXT NOT NULL,
email TEXT
)`
this.rdbStore = await relationalStore.getRdbStore(this.context, STORE_CONFIG)
await this.rdbStore.executeSql(sql)
console.info('Contact database initialized')
} catch (err) {
console.error(`Failed to initialize database: ${JSON.stringify(err)}`)
}
}
// 插入联系人
async insert(uri: string, valueBucket: dataAbility.ValuesBucket): Promise<number> {
if (!this.rdbStore) {
console.error('RdbStore is not initialized')
return -1
}
try {
const result = await this.rdbStore.insert(CONTACTS_TABLE, valueBucket)
console.info(`Insert contact successfully, rowId: ${result}`)
return result
} catch (err) {
console.error(`Failed to insert contact: ${JSON.stringify(err)}`)
return -1
}
}
// 查询联系人
async query(
uri: string,
columns: Array<string>,
predicates: dataAbility.DataAbilityPredicates
): Promise<dataAbility.ResultSet> {
if (!this.rdbStore) {
console.error('RdbStore is not initialized')
return {} as dataAbility.ResultSet
}
try {
const result = await this.rdbStore.query(
predicates,
columns
)
console.info('Query contacts successfully')
return result
} catch (err) {
console.error(`Failed to query contacts: ${JSON.stringify(err)}`)
return {} as dataAbility.ResultSet
}
}
// 更新联系人
async update(
uri: string,
valueBucket: dataAbility.ValuesBucket,
predicates: dataAbility.DataAbilityPredicates
): Promise<number> {
if (!this.rdbStore) {
console.error('RdbStore is not initialized')
return -1
}
try {
const rowsAffected = await this.rdbStore.update(
valueBucket,
predicates
)
console.info(`Update contact successfully, rows affected: ${rowsAffected}`)
return rowsAffected
} catch (err) {
console.error(`Failed to update contact: ${JSON.stringify(err)}`)
return -1
}
}
// 删除联系人
async delete(
uri: string,
predicates: dataAbility.DataAbilityPredicates
): Promise<number> {
if (!this.rdbStore) {
console.error('RdbStore is not initialized')
return -1
}
try {
const rowsDeleted = await this.rdbStore.delete(
predicates
)
console.info(`Delete contact successfully, rows deleted: ${rowsDeleted}`)
return rowsDeleted
} catch (err) {
console.error(`Failed to delete contact: ${JSON.stringify(err)}`)
return -1
}
}
}
2. 在module.json5中注册DataAbility
{
"module": {
"abilities": [
{
"name": "ContactDataAbility",
"type": "data",
"uri": "dataability:///com.example.contactdataability",
"exported": true,
"label": "Contact Data Ability",
"icon": "$media:icon",
"readPermission": "",
"writePermission": "",
"metadata": [
{
"name": "ohos.ability.dataability",
"resource": "$profile:dataability_config"
}
]
}
]
}
}
3. 客户端使用DataAbilityHelper访问数据
创建ContactManager.ts
客户端代码:
// ContactManager.ts
import dataAbility from '@ohos.ability.dataAbility'
import relationalStore from '@ohos.data.relationalStore'
const CONTACT_URI = 'dataability:///com.example.contactdataability'
export class ContactManager {
private dataAbilityHelper: dataAbility.DataAbilityHelper
constructor(context: Context) {
this.dataAbilityHelper = dataAbility.createDataAbilityHelper(context)
}
// 添加联系人
async addContact(name: string, phone: string, email?: string): Promise<number> {
const valueBucket: dataAbility.ValuesBucket = {
'name': name,
'phone': phone
}
if (email) {
valueBucket['email'] = email
}
try {
const result = await this.dataAbilityHelper.insert(CONTACT_URI, valueBucket)
console.info(`Contact added successfully with ID: ${result}`)
return result
} catch (err) {
console.error(`Failed to add contact: ${JSON.stringify(err)}`)
return -1
}
}
// 获取所有联系人
async getAllContacts(): Promise<Array<Contact>> {
const columns = ['id', 'name', 'phone', 'email']
const predicates = new dataAbility.DataAbilityPredicates()
predicates.equalTo('id', '*') // 查询所有记录
try {
const result = await this.dataAbilityHelper.query(
CONTACT_URI,
columns,
predicates
)
const contacts: Array<Contact> = []
if (result.rowCount > 0) {
while (result.goToNextRow()) {
contacts.push({
id: result.getLong(result.getColumnIndex('id')),
name: result.getString(result.getColumnIndex('name')),
phone: result.getString(result.getColumnIndex('phone')),
email: result.getString(result.getColumnIndex('email'))
})
}
}
console.info(`Retrieved ${contacts.length} contacts`)
return contacts
} catch (err) {
console.error(`Failed to query contacts: ${JSON.stringify(err)}`)
return []
}
}
// 更新联系人
async updateContact(
id: number,
updates: { name?: string; phone?: string; email?: string }
): Promise<boolean> {
const valueBucket: dataAbility.ValuesBucket = {}
if (updates.name) valueBucket['name'] = updates.name
if (updates.phone) valueBucket['phone'] = updates.phone
if (updates.email) valueBucket['email'] = updates.email
const predicates = new dataAbility.DataAbilityPredicates()
predicates.equalTo('id', id)
try {
const rowsAffected = await this.dataAbilityHelper.update(
CONTACT_URI,
valueBucket,
predicates
)
console.info(`Updated ${rowsAffected} contact(s)`)
return rowsAffected > 0
} catch (err) {
console.error(`Failed to update contact: ${JSON.stringify(err)}`)
return false
}
}
// 删除联系人
async deleteContact(id: number): Promise<boolean> {
const predicates = new dataAbility.DataAbilityPredicates()
predicates.equalTo('id', id)
try {
const rowsDeleted = await this.dataAbilityHelper.delete(
CONTACT_URI,
predicates
)
console.info(`Deleted ${rowsDeleted} contact(s)`)
return rowsDeleted > 0
} catch (err) {
console.error(`Failed to delete contact: ${JSON.stringify(err)}`)
return false
}
}
}
interface Contact {
id: number
name: string
phone: string
email?: string
}
4. UI界面调用DataAbility
创建ContactListPage.ets
显示联系人列表:
// ContactListPage.ets
import { ContactManager } from '../model/ContactManager'
@Entry
@Component
struct ContactListPage {
private contactManager: ContactManager = new ContactManager(getContext(this))
@State contacts: Array<Contact> = []
@State newName: string = ''
@State newPhone: string = ''
aboutToAppear() {
this.loadContacts()
}
async loadContacts() {
this.contacts = await this.contactManager.getAllContacts()
}
async addContact() {
if (this.newName && this.newPhone) {
await this.contactManager.addContact(this.newName, this.newPhone)
this.newName = ''
this.newPhone = ''
await this.loadContacts()
}
}
build() {
Column() {
// 添加联系人表单
Row() {
TextInput({ placeholder: 'Name', text: this.newName })
.onChange((value: string) => {
this.newName = value
})
.layoutWeight(1)
.margin(5)
TextInput({ placeholder: 'Phone', text: this.newPhone })
.onChange((value: string) => {
this.newPhone = value
})
.layoutWeight(1)
.margin(5)
Button('Add')
.onClick(() => this.addContact())
.margin(5)
}
.width('100%')
.padding(10)
// 联系人列表
List({ space: 10 }) {
ForEach(this.contacts, (contact: Contact) => {
ListItem() {
ContactItem({ contact: contact, onDeleted: () => this.loadContacts() })
}
}, (contact: Contact) => contact.id.toString())
}
.layoutWeight(1)
.width('100%')
}
.height('100%')
.width('100%')
}
}
@Component
struct ContactItem {
private contactManager: ContactManager = new ContactManager(getContext(this))
@Prop contact: Contact
@Link onDeleted: () => void
async deleteContact() {
const success = await this.contactManager.deleteContact(this.contact.id)
if (success) {
this.onDeleted()
}
}
build() {
Row() {
Column() {
Text(this.contact.name)
.fontSize(18)
.fontWeight(FontWeight.Bold)
Text(this.contact.phone)
.fontSize(16)
if (this.contact.email) {
Text(this.contact.email)
.fontSize(14)
.fontColor(Color.Gray)
}
}
.layoutWeight(1)
Button('Delete')
.onClick(() => this.deleteContact())
.backgroundColor(Color.Red)
.fontColor(Color.White)
}
.width('100%')
.padding(10)
.borderRadius(5)
.backgroundColor('#f5f5f5')
.margin({ top: 5, bottom: 5 })
}
}
四、DataAbility最佳实践
- 权限控制:为敏感数据设置读写权限
- 性能优化:批量操作减少跨进程通信次数
- 错误处理:全面捕获和处理可能的数据操作异常
- 数据验证:在DataAbility中验证输入数据的有效性
- 事务支持:对多个相关操作使用事务保证数据一致性
五、总结
HarmonyOS 5的DataAbility组件为应用间数据共享提供了安全高效的解决方案。通过标准化的接口和URI机制,开发者可以轻松实现跨应用数据访问,同时保持对数据安全的控制。本文展示的完整联系人管理示例演示了DataAbility的核心功能实现,可以作为开发实际项目的参考基础。
更多推荐
所有评论(0)