HarmonyOS鸿蒙Next中在ArkTS Stage模型中如何实现页面间共享同一个数据库实例?

HarmonyOS鸿蒙Next中在ArkTS Stage模型中如何实现页面间共享同一个数据库实例? 应用包含多个页面,希望所有页面操作同一份 SQLite 数据库,避免重复初始化或数据不一致。

4 回复

【解决方案】

开发者您好,可以封装一个全局单例的数据库工具类,参考HMOS世界中的PreferenceManager工具类

更多关于HarmonyOS鸿蒙Next中在ArkTS Stage模型中如何实现页面间共享同一个数据库实例?的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


把操纵数据库的代码总结到一个类中,然后搞成单例模式的,然后整个APP都用它就行了~~

在ArkTS Stage模型中,通过UIAbilityContext获取数据库实例。在EntryAbility中创建数据库后,使用UIAbilityContext的callee对象将数据库实例传递给其他Ability。接收方Ability通过caller对象获取该实例,实现跨页面共享。

在HarmonyOS Next的ArkTS Stage模型中,可以通过AppStorageUIAbility的上下文来实现页面间共享同一个数据库实例,核心思路是将数据库实例作为全局状态或Ability级别的单例进行管理。

推荐方案:在UIAbility中创建并共享实例

这是最直接且符合Stage模型生命周期管理的方式。数据库实例在UIAbility的onCreate()生命周期中创建,并通过UIAbility的上下文(context)或一个全局的静态变量/管理器,提供给该Ability下的所有页面(WindowStage中的页面)使用。

步骤示例:

  1. 创建数据库管理类:封装数据库的初始化、获取实例等操作。

    // DatabaseManager.ts
    import relationalStore from '@ohos.data.relationalStore';
    import common from '@ohos.app.ability.common';
    
    export class DatabaseManager {
      private static instance: relationalStore.RdbStore | null = null;
      private static context: common.UIAbilityContext | null = null;
    
      // 初始化,在UIAbility的onCreate中调用
      static async initDatabase(context: common.UIAbilityContext) {
        if (!this.instance) {
          const config: relationalStore.StoreConfig = {
            name: 'myApp.db', // 数据库名
            securityLevel: relationalStore.SecurityLevel.S1 // 安全级别
          };
          this.context = context;
          this.instance = await relationalStore.getRdbStore(context, config);
          // 这里可以执行建表等初始化操作
          // await this.instance.executeSql('CREATE TABLE IF NOT EXISTS ...');
        }
        return this.instance;
      }
    
      // 获取数据库实例(供页面调用)
      static getDatabase(): relationalStore.RdbStore {
        if (!this.instance) {
          throw new Error('Database not initialized. Call initDatabase first.');
        }
        return this.instance;
      }
    
      // 关闭数据库(在UIAbility的onDestroy中可选调用)
      static async closeDatabase() {
        if (this.instance) {
          await this.instance.close();
          this.instance = null;
        }
      }
    }
    
  2. 在UIAbility中初始化

    // EntryAbility.ets
    import UIAbility from '@ohos.app.ability.UIAbility';
    import { DatabaseManager } from './DatabaseManager';
    
    export default class EntryAbility extends UIAbility {
      onCreate(want, launchParam) {
        // 初始化数据库
        DatabaseManager.initDatabase(this.context);
        // ... 其他初始化
      }
    
      onDestroy() {
        // 应用退出时关闭数据库
        DatabaseManager.closeDatabase();
        // ... 其他清理
      }
    }
    
  3. 在任何页面中使用共享的数据库实例

    // 任意Page.ets
    import { DatabaseManager } from '../DatabaseManager';
    
    @Entry
    @Component
    struct MyPage {
      private rdbStore: relationalStore.RdbStore = DatabaseManager.getDatabase();
    
      build() {
        // ...
      }
    
      // 示例:插入数据
      async insertData() {
        const valueBucket: relationalStore.ValuesBucket = {
          'name': '张三',
          'age': 25
        };
        try {
          await this.rdbStore.insert('my_table', valueBucket);
        } catch (err) {
          console.error(`Insert failed, code: ${err.code}, message: ${err.message}`);
        }
      }
    }
    

关键点说明

  • 单例模式DatabaseManager 确保了在整个UIAbility生命周期内,getDatabase() 返回的是同一个 RdbStore 实例。
  • 生命周期对齐:数据库在UIAbility创建时初始化,在销毁时关闭,其生命周期与Ability绑定,避免了资源泄漏。
  • 线程安全RdbStore 的操作是异步的(返回Promise),但实例本身在多个页面间共享是安全的。请确保在一个操作完成后再进行下一个操作,或使用队列管理并发。
  • 数据一致性:所有页面通过同一个实例操作数据库,天然保证了数据视图的一致性。

替代方案:使用AppStorage

如果数据库实例非常简单,且你希望它在整个应用(多个UIAbility)中共享,可以考虑将其绑定到AppStorage。但通常更推荐上述基于UIAbility的方案,因为数据库资源通常与特定的Ability生命周期关联更紧密。

// 初始化后存入AppStorage
import AppStorage from '@ohos.app.ability.AppStorage';
AppStorage.setOrCreate('rdbStore', databaseInstance);

// 在页面中获取
@StorageProp('rdbStore') rdbStore: relationalStore.RdbStore;

总结:在ArkTS Stage模型中,通过在UIAbility中初始化数据库,并以单例模式提供获取接口,是实现多个页面共享同一数据库实例的标准且可靠的方法。这确保了高效的数据访问和一致的生命周期管理。

回到顶部