HarmonyOS 鸿蒙Next 多模块引用单例的问题

之前安照文档理解实现单例代码如下HZPhotoProcessor 单例

static sProcessor: HZPhotoProcessor | undefined
private constructor() {
}

public static sharedProcessor(): HZPhotoProcessor | undefined {
return HZPhotoProcessor.sProcessor;
}

发现在entry module调用HZPhotoProcessor.sharedProcessor() 产生实例跟 sdk module 调用产生的实例不是同一个。后来发现AppStorage组件存储是应用级别的,目前的实现单例代码的方案如下,经过验证没有问题是单例

public static sharedManager(): HZCameraManager {
  let instance = AppStorage.get<HZCameraManager>("HZCameraManager")
  if (instance == undefined || instance == null) {
    HZCameraManager.instance = new HZCameraManager();
    AppStorage.setOrCreate<HZCameraManager>("HZCameraManager", HZCameraManager.instance)
    instance = HZCameraManager.instance;
  }

  return instance;
}

这种实现方案是否是最佳实践,有没有其它的方案。如有,请给出代码示例。

使用背景: 目前使用多线程解压文件,使用woker组件,引用单例,遇到问题报错, AppStorage is not defined,如果不能使用AppStorage取单例对象,那么我们的单例需要改造。


更多关于HarmonyOS 鸿蒙Next 多模块引用单例的问题的实战教程也可以访问 https://www.itying.com/category-93-b0.html

2 回复
AppStorage应用全局的UI状态存储 :https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V5/arkts-appstorage-V5

AppStorage是一个用于存储应用程序数据的属性包装器,它只能在主线程中使用。如果在Taskpool中尝试使用AppStorage,可能会导致数据不一致或者崩溃等问题。因此,应该确保在使用AppStorage时只在主线程中操作。

如果您这是为了数据持久化,可以用sendablePreferences。

以下的单例支持多har包和对线程的唯一性

import { Context } from '@kit.AbilityKit';

import { sendablePreferences } from ‘@kit.ArkData’;

import { lang } from ‘@kit.ArkTS’;

export  class PreferenceUtil{

  private pref: sendablePreferences.Preferences | undefined = undefined

  private static instance: PreferenceUtil ;

  public static getInstance(): PreferenceUtil {

    if (PreferenceUtil.instance == null) {

      PreferenceUtil.instance = new PreferenceUtil();

      console.debug('PreferenceUtil getInstance  new  ')

    }

    return PreferenceUtil.instance ;

  }

  loadPreference(context:Context,storeName:string){

    try { // 加载preferences

      this.pref = sendablePreferences.getPreferencesSync(context,{ name: storeName})

      console.debug(加载Preferences成功)

    } catch (e) {

      console.info(加载Preferences失败, JSON.stringify(e))

    }

  }

  async putPreferenceValue(key: string, value: lang.ISendable){

    if (!this.pref) {

      console.debug(Preferences 尚未初始化!)

      return

    }

    try {

      // 写入数据

      this.pref.putSync(key, value)

      // 刷盘

      await this.pref.flush()

      console.debug(保存Preferences[${key} = ${value}]成功)

    } catch (e) {

      console.debug(保存Preferences[${key} = ${value}]失败, JSON.stringify(e))

    }

  }

  async getPreferenceValue(key: string, defaultValue: lang.ISendable){

    if (!this.pref) {

      console.debug(Preferences 尚未初始化!)

      return

    }

    try {

      // 读数据

      let value = this.pref.getSync(key, defaultValue)

      console.debug(读取Preferences[${key} = ${value}]成功)

      return value

    } catch (e) {

      console.debug(读取Preferences[${key}]失败, JSON.stringify(e))

      return

    }

  }

}<button style="position: absolute; padding: 4px 8px 0px; cursor: pointer; top: 8px; right: 8px; font-size: 14px;">复制</button>

更多关于HarmonyOS 鸿蒙Next 多模块引用单例的问题的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


在HarmonyOS鸿蒙Next系统中,处理多模块引用单例的问题时,可以通过全局服务注册和获取机制来确保单例实例在整个系统中的唯一性。

鸿蒙系统提供了系统级服务注册和获取接口,允许你在一个模块中注册服务,并在其他模块中通过服务名称获取该服务实例。这样,即使多个模块需要访问同一个单例对象,也可以通过系统服务管理器来确保它们访问的是同一个实例。

具体实现步骤如下:

  1. 在提供单例的模块中,通过系统服务管理器注册服务。这通常涉及创建一个服务实现类,并在该类中实现所需的功能,然后调用系统服务注册接口将该服务注册到系统中。

  2. 在需要使用单例的模块中,通过系统服务管理器获取服务。使用与注册时相同的服务名称来调用获取接口,系统将返回已注册的服务实例。

需要注意的是,服务注册和获取应在系统启动时或适当的生命周期内进行,以确保服务的可用性和稳定性。

此外,鸿蒙系统还提供了服务版本管理和生命周期管理等功能,允许开发者更灵活地控制服务的更新和释放。

如果问题依旧没法解决请联系官网客服,官网地址是:https://www.itying.com/category-93-b0.html

回到顶部