一、HarmonyOS 5中DataAbility的核心概念

在HarmonyOS 5应用开发中,DataAbility是实现数据共享和持久化存储的关键组件。它基于Ability框架,为应用提供了标准化的数据访问接口,允许不同应用间安全地共享数据。

DataAbility的核心特点包括:

  1. 统一数据访问:通过URI标准化数据访问路径
  2. 跨进程通信:支持不同应用间的安全数据交互
  3. 多种数据源支持:可对接关系型数据库、文件系统等存储后端
  4. 生命周期管理:系统统一管理数据组件的创建和销毁

二、创建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. 性能优化建议

  1. 索引优化:为常用查询字段创建索引
  2. 批量操作:优先使用batchInsert和executeBatch
  3. 结果集处理:及时关闭ResultSet避免内存泄漏
  4. 异步处理:避免在主线程执行耗时数据库操作

四、总结

本文详细介绍了在HarmonyOS 5中创建和使用DataAbility的完整流程。通过实现标准的CRUD接口,开发者可以构建高效、安全的数据访问层。DataAbility的强大之处在于:

  1. 提供了标准化的数据访问接口
  2. 支持跨应用数据共享
  3. 内置事务处理机制
  4. 与HarmonyOS生态深度集成

随着HarmonyOS 5的不断发展,DataAbility将继续在分布式数据管理和跨设备数据共享方面发挥重要作用。

Logo

讨论HarmonyOS开发技术,专注于API与组件、DevEco Studio、测试、元服务和应用上架分发等。

更多推荐