HarmonyOS 鸿蒙Next关于HAP/HAR与单例的问题

发布于 1周前 作者 vueper 最后一次编辑是 5天前 来自 鸿蒙OS

HarmonyOS 鸿蒙Next关于HAP/HAR与单例的问题

为了验证文档中说明的HAR会copy多份被打包到不同依赖方,做了如下实验,发现有点奇怪,希望得到解释

前提:在HAR的Page1 声明一个单例

export class Singleton {
  static instance = new Singleton()
  history: string[] = []
}
<button style="position: absolute; padding: 4px 8px 0px; cursor: pointer; top: 4px; right: 8px; font-size: 14px;">复制</button>

HAP1、HAP2均依赖了HAR

场景1 : HAP 1 跳转到 HAR 的 page1,page1 给数组添加字符串,返回到HAP1, 跳转到HAP2的页面, HAP2再跳转到HAR的page1, 给数组添加字符串,此时发现数组有两个对象 (预期应该是只有一个对象?)

场景2: HAP1直接给HAR的单例的数组属性添加字符串,此时发现数组有一个对象,HAP1跳转到HAP2的页面, 直接给HAR的单例的数组属性添加字符串,此时发现数组有一个对象。(此时应该是符合预期的)

场景3: HAP1跳转到HAR的page1, page1 给数组添加字符,返回到HAP1,打印单例的数组属性,此时有一个对象。HAP1跳转到HAP2的页面,HAP2直接给HAR的单例的数组属性添加字符串,此时打印数组发现只有一个对象,HAP2跳转到HAR的page1,给单例的数组属性添加字符串,此时发现数组有两个对象。重新回到HAP1, 此时打印数组有1个对象,从HAP1 跳转到HAR1的page1, 打印数组,此时有两个对象。(结论:HAP2的HAR和HAP1的HAR共享了单例对象,但是HAP1自己独立了单例对象)

4 回复

HAR.ets

import { router } from '[@kit](/user/kit).ArkUI';

export class Singleton {
static instance = new Singleton()
history: string[] = []
}


[@Entry](/user/Entry)({ routeName: 'HARPage1'})
[@Component](/user/Component)
export struct MainPage {

[@State](/user/State) singleton: Singleton = Singleton.instance

[@State](/user/State) color: Color = Color.White

build() {
Column({space: 20}) {
Blank()
Text("HAR Page")
.fontSize(50)
.fontWeight(FontWeight.Bold)
Button("数组添加内容")
.onClick(() => {
this.singleton.history.push(`Change Name_${Math.floor(Math.random() * 100)}`)
})
Button("打印单例中的数组")
.onClick(() => {
AlertDialog.show({
message: JSON.stringify(this.singleton.history)
})
})
Button("Background")
.onClick(() => {
this.color = Color.Green
})
Button("Back")
.onClick(() => {
router.back()
})
Blank()
}
.backgroundColor(this.color)
.width('100%')
.height('30%')
}
}

HAP2 index.ets

import { common } from '[@kit](/user/kit).AbilityKit'
import { BusinessError } from '[@kit](/user/kit).BasicServicesKit'
import { router } from '[@kit](/user/kit).ArkUI'
import { Singleton } from '[@ohos](/user/ohos)/HARLibraryA'

[@Entry](/user/Entry)
[@Component](/user/Component)
struct Index {
context = getContext(this) as common.UIAbilityContext

[@State](/user/State) clickTime: number = 0

singleton = Singleton.instance

build() {
Column({ space: 20 }) {
Blank()
Text("Second Entry")
.fontSize(30)
.fontWeight(FontWeight.Medium)
Button('跳转到同一个HAR')
.onClick(() => {
router.pushNamedRoute({
name: "HARPage1",
params: {
"from": "second ability"
}
})
})
Button("单例的数组添加内容")
.onClick(() => {
this.singleton.history.push("HAP2")
})
Button("打印单例中的数组")
.onClick(() => {
AlertDialog.show({
message: JSON.stringify(this.singleton.history)
})
})
Button("Back")
.onClick(() => {
this.context.terminateSelf((error: BusinessError) => {
console.log(`terminateSelf failed, code is ${error.code}, message is ${error.message}`)
return
})
})
Blank()
}
.height('100%')
.width('100%')
}
}

HAP1 entry.ets

import { common, Want } from '[@kit](/user/kit).AbilityKit'
import { MainPage, Singleton } from '[@ohos](/user/ohos)/HARLibraryA'
import { router } from '[@kit](/user/kit).ArkUI'

[@Entry](/user/Entry)
[@Component](/user/Component)
struct Index {

[@State](/user/State) clickTime: number = 0

singleton = Singleton.instance

context = getContext(this) as common.UIAbilityContext
build() {
Column({ space: 20 }) {
Blank()
Text("Ability")
.fontSize(30)
.fontWeight(FontWeight.Medium)
Button("跳转到另一个Ability")
.onClick(() => {
let want: Want = {
bundleName: "com.example.testsdk",
abilityName: "SecondEntryAbility"
}
this.context.startAbility(want).then(() => {
console.log("跳转成功")
}).catch((error: Error) => {
console.log(`跳转失败: ${error.message}`)
})
})
Button("跳转到另一个HAR -- Router")
.type(ButtonType.Normal)
.backgroundColor(Color.Red)
.border({
radius: 10
})
.onClick(() => {
router.pushNamedRoute({
name: "HARPage1",
params: {
'from': 'first ability'
}
})
})
Button("单例的数组添加内容")
.onClick(() => {
this.singleton.history.push("HAP1")
})
Button("打印单例中的数组")
.onClick(() => {
AlertDialog.show({
message: JSON.stringify(this.singleton.history)
})
})
Blank()
}
.height('100%')
.width('100%')
}
}

关于HarmonyOS鸿蒙Next中HAP/HAR与单例的问题,HAP(Harmony Ability Package)是应用的基本单元,而HAR(Harmony Archive)是静态共享包,可被多个HAP依赖。单例模式在HarmonyOS中用于确保类的一个全局唯一实例。若HAR中的单例被多个HAP依赖并操作,可能会出现数据不一致的情况,因为每个HAP可能加载了HAR的不同实例或由于内存隔离等原因导致数据不共享。请检查单例实现是否正确,并确保在全局范围内唯一。如果问题依旧没法解决请加我微信,我的微信是itying888。

回到顶部