#跟着坚果学鸿蒙# HarmonyOS 5 创建DataAbility完全指南:从理论到实践
·
一、HarmonyOS 5中DataAbility的核心概念
在HarmonyOS 5应用开发中,DataAbility是实现数据共享和持久化存储的关键组件。它基于Ability框架,为应用提供了标准化的数据访问接口,允许不同应用间安全地共享数据。
DataAbility的核心特点包括:
- 统一数据访问:通过URI标准化数据访问路径
- 跨进程通信:支持不同应用间的安全数据交互
- 多种数据源支持:可对接关系型数据库、文件系统等存储后端
- 生命周期管理:系统统一管理数据组件的创建和销毁
二、创建DataAbility的完整流程
1. 初始化数据库环境
首先我们需要创建DataAbility类并初始化数据库环境。以下是完整的ArkTS实现代码:
import featureAbility from '@ohos.ability.featureAbility';
import type common from '@ohos.app.ability.common';
import type Want from '@ohos.app.ability.Want';
import type { AsyncCallback, BusinessError } from '@ohos.base';
import dataAbility from '@ohos.data.dataAbility';
import rdb from '@ohos.data.rdb';
import hilog from '@ohos.hilog';
const TABLE_NAME = 'book';
const STORE_CONFIG: rdb.StoreConfig = {
name: 'book.db',
securityLevel: rdb.SecurityLevel.S1
};
const SQL_CREATE_TABLE = `
CREATE TABLE IF NOT EXISTS ${TABLE_NAME} (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL,
introduction TEXT NOT NULL,
price REAL,
create_time TEXT
)`;
let rdbStore: rdb.RdbStore | undefined = undefined;
const TAG: string = '[BookDataAbility]';
const DOMAIN: number = 0xFF00;
class BookDataAbility {
// 初始化数据库
onInitialized(want: Want): void {
hilog.info(DOMAIN, TAG, 'DataAbility initialized for: ' + want.bundleName);
const context: common.BaseContext = {
stageMode: featureAbility.getContext().stageMode
};
rdb.getRdbStore(context, STORE_CONFIG, 1, (err, store) => {
if (err) {
hilog.error(DOMAIN, TAG, `Failed to get RdbStore: ${err.code}, ${err.message}`);
return;
}
store.executeSql(SQL_CREATE_TABLE, [], (err) => {
if (err) {
hilog.error(DOMAIN, TAG, `Failed to create table: ${err.code}, ${err.message}`);
} else {
hilog.info(DOMAIN, TAG, 'Book table created successfully');
rdbStore = store;
// 创建索引提升查询性能
store.executeSql(
'CREATE INDEX IF NOT EXISTS book_name_idx ON book(name)',
[],
(err) => {
if (err) {
hilog.error(DOMAIN, TAG, `Failed to create index: ${err.message}`);
}
}
);
}
});
});
}
// 继续实现其他接口...
}
2. 实现CRUD操作接口
DataAbility的核心是实现数据操作接口。以下是完整的CRUD操作实现:
class BookDataAbility {
// ...接上部分代码
// 插入单条数据
insert(uri: string, valueBucket: rdb.ValuesBucket, callback: AsyncCallback<number>): void {
hilog.info(DOMAIN, TAG, 'Insert operation started');
if (!rdbStore) {
callback(new Error('RdbStore not initialized') as BusinessError, -1);
return;
}
// 添加创建时间戳
valueBucket['create_time'] = new Date().toISOString();
rdbStore.insert(TABLE_NAME, valueBucket, callback);
}
// 批量插入数据
batchInsert(uri: string, valueBuckets: Array<rdb.ValuesBucket>, callback: AsyncCallback<number>): void {
hilog.info(DOMAIN, TAG, `Batch insert started with ${valueBuckets.length} records`);
if (!rdbStore) {
callback(new Error('RdbStore not initialized') as BusinessError, -1);
return;
}
let successCount = 0;
const totalCount = valueBuckets.length;
const insertNext = (index: number) => {
if (index >= totalCount) {
callback(null, successCount);
return;
}
const valueBucket = valueBuckets[index];
valueBucket['create_time'] = new Date().toISOString();
rdbStore.insert(TABLE_NAME, valueBucket, (err, rowId) => {
if (err) {
hilog.error(DOMAIN, TAG, `Failed to insert record ${index}: ${err.message}`);
} else {
successCount++;
hilog.debug(DOMAIN, TAG, `Inserted record ${index} with rowId: ${rowId}`);
}
insertNext(index + 1);
});
};
insertNext(0);
}
// 查询数据
query(
uri: string,
columns: Array<string>,
predicates: dataAbility.DataAbilityPredicates,
callback: AsyncCallback<rdb.ResultSet>
): void {
hilog.info(DOMAIN, TAG, 'Query operation started');
if (!rdbStore) {
callback(new Error('RdbStore not initialized') as BusinessError, {} as rdb.ResultSet);
return;
}
const rdbPredicates = dataAbility.createRdbPredicates(TABLE_NAME, predicates);
// 默认查询所有列
const queryColumns = columns && columns.length > 0 ? columns : ['*'];
rdbStore.query(rdbPredicates, queryColumns, callback);
}
// 更新数据
update(
uri: string,
valueBucket: rdb.ValuesBucket,
predicates: dataAbility.DataAbilityPredicates,
callback: AsyncCallback<number>
): void {
hilog.info(DOMAIN, TAG, 'Update operation started');
if (!rdbStore) {
callback(new Error('RdbStore not initialized') as BusinessError, -1);
return;
}
const rdbPredicates = dataAbility.createRdbPredicates(TABLE_NAME, predicates);
rdbStore.update(valueBucket, rdbPredicates, callback);
}
// 删除数据
delete(
uri: string,
predicates: dataAbility.DataAbilityPredicates,
callback: AsyncCallback<number>
): void {
hilog.info(DOMAIN, TAG, 'Delete operation started');
if (!rdbStore) {
callback(new Error('RdbStore not initialized') as BusinessError, -1);
return;
}
const rdbPredicates = dataAbility.createRdbPredicates(TABLE_NAME, predicates);
rdbStore.delete(rdbPredicates, callback);
}
}
export default new BookDataAbility();
3. 在UI中使用DataAbility
下面是一个完整的ArkUI页面示例,展示如何使用DataAbility进行数据操作:
// pages/BookList.ets
import { BookDataAbility } from '../ability/BookDataAbility';
import { BusinessError } from '@ohos.base';
import router from '@ohos.router';
@Entry
@Component
struct BookList {
@State books: Array<any> = [];
@State loading: boolean = true;
build() {
Column() {
List({ space: 10 }) {
ForEach(this.books, (book) => {
ListItem() {
Row() {
Column() {
Text(book.name)
.fontSize(18)
.fontWeight(FontWeight.Bold)
Text(book.introduction)
.fontSize(14)
.margin({ top: 5 })
}
.layoutWeight(1)
Button('删除')
.type(ButtonType.Capsule)
.onClick(() => this.deleteBook(book.id))
}
.padding(10)
}
.borderRadius(10)
.backgroundColor(Color.White)
.shadow({ radius: 5, color: '#888', offsetX: 1, offsetY: 1 })
})
}
.layoutWeight(1)
.divider({ strokeWidth: 1, color: '#EEE' })
Button('添加新书')
.width('90%')
.height(50)
.margin(10)
.onClick(() => router.pushUrl({ url: 'pages/AddBook' }))
}
.width('100%')
.height('100%')
.backgroundColor('#F5F5F5')
.onAppear(() => this.loadBooks())
}
private loadBooks() {
this.loading = true;
const predicates = new dataAbility.DataAbilityPredicates();
predicates.orderByAsc('name');
BookDataAbility.query(
'',
['id', 'name', 'introduction'],
predicates,
(err: BusinessError, resultSet: rdb.ResultSet) => {
if (err) {
console.error('Failed to query books:', err);
return;
}
const books = [];
while (resultSet.goToNextRow()) {
books.push({
id: resultSet.getLong(resultSet.getColumnIndex('id')),
name: resultSet.getString(resultSet.getColumnIndex('name')),
introduction: resultSet.getString(resultSet.getColumnIndex('introduction'))
});
}
this.books = books;
this.loading = false;
resultSet.close();
}
);
}
private deleteBook(id: number) {
const predicates = new dataAbility.DataAbilityPredicates();
predicates.equalTo('id', id);
BookDataAbility.delete('', predicates, (err: BusinessError, rowsDeleted: number) => {
if (err) {
console.error('Failed to delete book:', err);
return;
}
if (rowsDeleted > 0) {
this.loadBooks();
}
});
}
}
三、DataAbility的高级用法
1. 实现事务处理
关系型数据库的事务处理对于保证数据一致性至关重要。以下是事务处理的实现示例:
class BookDataAbility {
// ...接上部分代码
// 批量操作事务处理
executeBatch(
uri: string,
operations: Array<dataAbility.DataAbilityOperation>,
callback: AsyncCallback<Array<dataAbility.DataAbilityResult>>
): void {
hilog.info(DOMAIN, TAG, `Execute batch with ${operations.length} operations`);
if (!rdbStore) {
callback(new Error('RdbStore not initialized') as BusinessError, []);
return;
}
const results: Array<dataAbility.DataAbilityResult> = [];
// 开始事务
rdbStore.beginTransaction();
const processNext = (index: number) => {
if (index >= operations.length) {
// 提交事务
rdbStore.commit();
callback(null, results);
return;
}
const op = operations[index];
const predicates = op.predicates
? dataAbility.createRdbPredicates(TABLE_NAME, op.predicates)
: undefined;
switch (op.type) {
case featureAbility.DataAbilityOperationType.TYPE_INSERT:
rdbStore.insert(TABLE_NAME, op.valuesBucket, (err, rowId) => {
results.push({
uri: op.uri,
count: err ? 0 : 1
});
processNext(index + 1);
});
break;
case featureAbility.DataAbilityOperationType.TYPE_UPDATE:
if (!predicates) {
results.push({ uri: op.uri, count: 0 });
processNext(index + 1);
break;
}
rdbStore.update(op.valuesBucket, predicates, (err, rowsUpdated) => {
results.push({
uri: op.uri,
count: err ? 0 : rowsUpdated
});
processNext(index + 1);
});
break;
case featureAbility.DataAbilityOperationType.TYPE_DELETE:
if (!predicates) {
results.push({ uri: op.uri, count: 0 });
processNext(index + 1);
break;
}
rdbStore.delete(predicates, (err, rowsDeleted) => {
results.push({
uri: op.uri,
count: err ? 0 : rowsDeleted
});
processNext(index + 1);
});
break;
default:
results.push({ uri: op.uri, count: 0 });
processNext(index + 1);
}
};
try {
processNext(0);
} catch (err) {
// 回滚事务
rdbStore.rollback();
callback(err as BusinessError, []);
}
}
}
2. 性能优化建议
- 索引优化:为常用查询字段创建索引
- 批量操作:优先使用batchInsert和executeBatch
- 结果集处理:及时关闭ResultSet避免内存泄漏
- 异步处理:避免在主线程执行耗时数据库操作
四、总结
本文详细介绍了在HarmonyOS 5中创建和使用DataAbility的完整流程。通过实现标准的CRUD接口,开发者可以构建高效、安全的数据访问层。DataAbility的强大之处在于:
- 提供了标准化的数据访问接口
- 支持跨应用数据共享
- 内置事务处理机制
- 与HarmonyOS生态深度集成
随着HarmonyOS 5的不断发展,DataAbility将继续在分布式数据管理和跨设备数据共享方面发挥重要作用。
更多推荐
所有评论(0)