HarmonyOS鸿蒙Next中如何在子包中使用全局的Context

HarmonyOS鸿蒙Next中如何在子包中使用全局的Context 定义全局的 context

main_ability.cj:

var globalAbilityContext: Option<AbilityContext> = Option<AbilityContext>.None

class MainAbility <: Ability {
    public init() {
        super()
        registerSelf()
    }
    public override func onCreate(want: Want, launchParam: LaunchParam): Unit {
        AppLog.info("MainAbility OnCreated.${want.abilityName}")
        globalAbilityContext = Option<AbilityContext>.Some(this.context);
        match (launchParam.launchReason) {
            case LaunchReason.START_ABILITY => AppLog.info("START_ABILITY")
            case _ => ()
        }
    }

    public override func onWindowStageCreate(windowStage: WindowStage): Unit {
        AppLog.info("MainAbility onWindowStageCreate.")
        let appStageContext = getStageContext(globalAbilityContext.getOrThrow());
        DatabaseHelper(appStageContext)
        windowStage.loadContent("EntryView")
    }
}
func createAbility(): MainAbility {
    MainAbility()
}

let ABILITY_REGISTER_RESULT = Ability.registerCreator("CangjieAbility", createAbility)

public func get_app_Context(): CPointer<Unit> {
    return getStageContext(globalAbilityContext.getOrThrow())
}

定义了get_app_Context用来做全局的 context 使用,

在同一级,主包
package ohos_app_cangjie_entry
index.cj中定义了一个公共的方法,获取存储的值
//获取沙盒存储数据的值
public  func getPreferencesInfo(key:String){
        var my_preference = Preferences.getPreferences(get_app_Context(), CommonTagConstants.PRE_TAG);
        if (my_preference.has(key)){
            let value = my_preference.get(key,ValueType.string(''))
            match (value) {
                case ValueType.string(n) => return  n
                case _ => return ''
            }
        }
       return ''
    }

子包:

package ohos_app_cangjie_entry.databasemgr
子包的文件
BaseStoreQueryMgr.cj

package ohos_app_cangjie_entry.databasemgr

import ohos_app_cangjie_entry.getPreferencesInfo
import ohos_app_cangjie_entry.constants.CommonTagConstants

public class BaseStoreQueryMgr {
    /**
     * 查询今日路线门店数量
     */
    public static func getTodayRouteStoreCount() {
        let empId: String = getPreferencesInfo(CommonTagConstants.EMP_ID)
    }
}

在同级的 index.cj ,login.cj 中使用没有报错,但是我在子包中使用,就报错,报错信息:Error: combined package ‘ohos_app_cangjie_entry’ is depended (directly or indirectly) by its sub package ‘ohos_app_cangjie_entry.databasemgr’, cannot combine it,如何解决这个依赖冲突

这是目录结构

cke_18489.png


更多关于HarmonyOS鸿蒙Next中如何在子包中使用全局的Context的实战教程也可以访问 https://www.itying.com/category-93-b0.html

4 回复

【背景知识】

cjpm.toml:仓颉模块配置文件,用于配置一些基础信息、依赖项、编译选项等内容,cjpm主要通过这个文件进行解析执行。其中,模块名可以在cjpm.toml中进行重命名,但是包名不能在cjpm.toml中进行重命名。

【问题定位】

根据报错信息,提示父包被子包依赖,无法combine。检查配置文件是否中启用了combined配置,若启用了该配置可能会出现无法通过导入关系识别的循环依赖,导致编译报错。

【分析结论】

启用了combined配置,不允许子包直接或者间接依赖父包,导致编译报错。

【修改建议】

  • 查找并删除子包中存在的对父包的导入。
  • 去掉模块里cjpm.toml中的combined配置:
[profile]
  [profile.build]
    incremental = true
    lto = ""
    # 关闭combined配置
    # [profile.build.combined]
      # ohos_app_cangjie_entry = "dynamic"
  [profile.customized-option]
    debug = "-g -Woff all"
    release = "--fast-math -O2 -s -Woff all"
  [profile.test]

更多关于HarmonyOS鸿蒙Next中如何在子包中使用全局的Context的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


通过单例可以实现获取全局的context,可以避免子包之间的相互引用

在HarmonyOS Next中,子包通过AbilityStage获取全局Context。在模块的src/main/resources/module.json5中配置"context"字段,声明Context依赖。子包代码中调用AbilityStage.getContext()获取全局上下文对象,该对象提供应用资源管理、系统服务调用等基础能力。子包与主包共享同一个进程空间时,可通过此方式直接访问全局上下文。

在HarmonyOS Next中,子包不能直接依赖主包,这会导致循环依赖错误。你的问题在于子包ohos_app_cangjie_entry.databasemgr导入了主包ohos_app_cangjie_entry中的getPreferencesInfo函数。

解决方案:

  1. 将全局Context管理移到独立的共享模块
  2. 使用ArkTS的依赖注入机制
  3. 通过AbilityContext传递参数

推荐重构代码结构:

// 创建独立的context管理模块
public class AppContextManager {
    private static var abilityContext: AbilityContext | null = null
    
    public static setContext(context: AbilityContext) {
        this.abilityContext = context
    }
    
    public static getContext(): AbilityContext {
        return this.abilityContext
    }
}

// 在MainAbility中设置
public override func onCreate(want: Want, launchParam: LaunchParam): Unit {
    AppContextManager.setContext(this.context)
}

// 子包中直接使用AppContextManager
let context = AppContextManager.getContext()

这样避免了包之间的循环依赖,同时保持了Context的全局可用性。

回到顶部