From 59eeab6f9f6b7bfdafbd498648cdb189c55d9624 Mon Sep 17 00:00:00 2001 From: duke Date: Sat, 14 Jun 2025 11:50:39 +0800 Subject: [PATCH 1/2] =?UTF-8?q?feat(lifecycle):=20=E5=BA=95=E5=B1=82?= =?UTF-8?q?=E7=94=9F=E5=91=BD=E5=91=A8=E6=9C=9F=E6=84=9F=E7=9F=A5=E8=83=BD?= =?UTF-8?q?=E5=8A=9B=E6=9B=BF=E6=8D=A2=E6=88=90=20@duke/component-lifecycl?= =?UTF-8?q?e=20=E5=BA=93?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 简化代码,加强可维护性 - 添加 @duke/component-lifecycle 依赖 - 待 @duke/component-lifecycle 审核通过后替换成 中央仓库的链接在发布 --- CHANGELOG.md | 9 ++ README.md | 11 +- build-profile.json5 | 9 +- entry/oh-package-lock.json5 | 14 ++- entry/oh-package.json5 | 3 +- entry/src/main/ets/pages/CustView.ets | 11 +- entry/src/main/ets/pages/Index.ets | 10 +- entry/src/main/ets/pages/NextPage.ets | 4 +- entry/src/main/ets/workers/Worker.ets | 2 +- library/BuildProfile.ets | 2 +- library/CHANGELOG.md | 4 + library/README.md | 9 +- library/library.har | Bin 0 -> 9659 bytes library/oh-package.json5 | 5 +- library/src/main/ets/Constants.ts | 10 +- library/src/main/ets/Decorators.ts | 111 +++++++++-------- library/src/main/ets/EventOnInfo.ts | 5 +- library/src/main/ets/EventPostExtensions.ts | 129 ++++++++++++++++---- 18 files changed, 243 insertions(+), 105 deletions(-) create mode 100644 library/library.har diff --git a/CHANGELOG.md b/CHANGELOG.md index 69ce189..0457916 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,14 @@ # Changelog +## [v2.1.1] 2025.06.14 + +- 底层生命周期感知能力替换成@duke/component-lifecycle库,简化代码,加强可维护性 + +## [v2.1.0] 2025.06.11 + +- 修复装饰器模式下的多个订阅者下,只有一个订阅者会自动反注册的问题 +- 新增 onFromComponent 方法,使用更加灵活 + ## [v2.0.0] 2025.01.17 - 全新升级支持跨线程通知及跨线程粘性事件 diff --git a/README.md b/README.md index 898967d..5e1a39c 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,7 @@ -# 有没有公司招鸿蒙开发的啊,求职ing - # EventPost ## 简介 +[![openHarmony](https://img.shields.io/badge/openharmony-v2.1.1-brightgreen)](https://gitee.com/Duke_Bit/eventpost/releases/tag/v2.1.1) EventPost是一款消息总线,具有生命周期感知能力,支持Sticky。 @@ -129,4 +128,10 @@ DevEco Studio: 5.0.5.315, SDK: HarmonyOS 5.0.1 Release Ohos_sdk_public 5.0.1.115 ## 开源协议 -本项目基于 [MIT license](https://gitee.com/Duke_Bit/eventpost/blob/master/LICENSE) ,请自由地享受和参与开源。 \ No newline at end of file +本项目基于 [MIT license](https://gitee.com/Duke_Bit/eventpost/blob/master/LICENSE) ,请自由地享受和参与开源。 + +## 其他库 + +- @duke/component-lifecycle 鸿蒙版本的Lifecycle库,支持组件、Router和Navigation: [https://gitee.com/Duke_Bit/component-lifecycle](https://gitee.com/Duke_Bit/component-lifecycle) +- @duke/elf-dialog CustomDialog黑魔法 不依赖promptAction 实现的函数级弹窗,省去复杂的模版代码,让你专注于你的业务,一行代码搞定弹窗: [https://gitee.com/Duke_Bit/elf-dialog](https://gitee.com/Duke_Bit/elf-dialog) +- @duke/elf-refresh OpenHarmony 刷新组件,支持下拉刷新和上拉加载更多,支持各种组件,List、Grid,支持header,footer,目标打造HarmonyOS的SmartRefreshLayout: [https://gitee.com/Duke_Bit/ElfRefresh](https://gitee.com/Duke_Bit/ElfRefresh) \ No newline at end of file diff --git a/build-profile.json5 b/build-profile.json5 index 35c3b39..a086030 100644 --- a/build-profile.json5 +++ b/build-profile.json5 @@ -19,8 +19,15 @@ { "name": "default", "signingConfig": "default", - "compatibleSdkVersion": "4.1.0(11)", + "targetSdkVersion": "5.0.5(17)", + "compatibleSdkVersion": "5.0.0(12)", "runtimeOS": "HarmonyOS", + "buildOption": { + "strictMode": { + "caseSensitiveCheck": true, + "useNormalizedOHMUrl": true + } + } } ], "buildModeSet": [ diff --git a/entry/oh-package-lock.json5 b/entry/oh-package-lock.json5 index 99e7939..ff74946 100644 --- a/entry/oh-package-lock.json5 +++ b/entry/oh-package-lock.json5 @@ -5,17 +5,25 @@ "lockfileVersion": 3, "ATTENTION": "THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.", "specifiers": { - "EventPost@../library": "EventPost@../library", + "@duke/component-lifecycle@../library/library.har": "@duke/component-lifecycle@../library/library.har", + "eventpost@../library": "eventpost@../library", "libnative_event_post.so@../library/src/main/cpp/types/libeventpost": "libnative_event_post.so@../library/src/main/cpp/types/libeventpost" }, "packages": { - "EventPost@../library": { + "@duke/component-lifecycle@../library/library.har": { + "name": "@duke/component-lifecycle", + "version": "1.0.2", + "resolved": "../library/library.har", + "registryType": "local" + }, + "eventpost@../library": { "name": "eventpost", "version": "2.1.0", "resolved": "../library", "registryType": "local", "dependencies": { - "libnative_event_post.so": "file:./src/main/cpp/types/libeventpost" + "libnative_event_post.so": "file:./src/main/cpp/types/libeventpost", + "@duke/component-lifecycle": "file:./library.har" } }, "libnative_event_post.so@../library/src/main/cpp/types/libeventpost": { diff --git a/entry/oh-package.json5 b/entry/oh-package.json5 index 5f9348c..2d5b0c2 100644 --- a/entry/oh-package.json5 +++ b/entry/oh-package.json5 @@ -6,7 +6,8 @@ "author": "", "license": "", "dependencies": { - EventPost: "file:../library" + 'eventpost': "file:../library", + '@duke/component-lifecycle': "file:../library/library.har" } } diff --git a/entry/src/main/ets/pages/CustView.ets b/entry/src/main/ets/pages/CustView.ets index a7e10da..67f39b8 100644 --- a/entry/src/main/ets/pages/CustView.ets +++ b/entry/src/main/ets/pages/CustView.ets @@ -1,13 +1,22 @@ -import { Subscriber } from 'EventPost' +import { Subscriber } from 'eventpost' @Component export struct CustomView { @State name: string = "CustView" + aboutToAppear(): void { + console.log("aboutToAppear") + } + build() { Text(this.name) } + onDidBuild(): void { + let a = this as object as Record + console.log("onDidBuild"+a['_ComponentLifecycle']+'') + } + @Subscriber("test1") onReceived(event: object) { console.error("收到 test1 " + JSON.stringify(event)) diff --git a/entry/src/main/ets/pages/Index.ets b/entry/src/main/ets/pages/Index.ets index 237f753..8315d54 100644 --- a/entry/src/main/ets/pages/Index.ets +++ b/entry/src/main/ets/pages/Index.ets @@ -1,11 +1,13 @@ import { router } from '@kit.ArkUI'; -import { EventPost, Subscriber } from 'EventPost/Index'; +import { EventPost, Subscriber } from 'eventpost'; import { CustomView } from './CustView'; import { ErrorEvent, MessageEvents, worker } from '@kit.ArkTS'; +import { Lifecycle, LifecycleOwner } from '@duke/component-lifecycle'; @Entry @Component struct Index { + @LifecycleOwner lifecycle: Lifecycle = new Lifecycle(); @State message: string = 'Hello World'; @State showCustom: boolean = true @@ -22,6 +24,12 @@ struct Index { .fontSize(50) .fontWeight(FontWeight.Bold) + Button("重新加载测试") + .margin({ top: 16 }) + .onClick(() => { + this.showCustom = true; + }); + Button("销毁测试") .margin({ top: 16 }) .onClick(() => { diff --git a/entry/src/main/ets/pages/NextPage.ets b/entry/src/main/ets/pages/NextPage.ets index 0a4af13..0496258 100644 --- a/entry/src/main/ets/pages/NextPage.ets +++ b/entry/src/main/ets/pages/NextPage.ets @@ -1,4 +1,4 @@ -import { EventPost, Subscriber } from 'EventPost/Index'; +import { EventPost, Subscriber } from 'eventpost'; @Entry @Component @@ -41,7 +41,7 @@ struct NextPage { console.log("1111") this.message = "fff" EventPost.getDefault().onFromComponent('test1',this,()=>{ - console.log("2222") + console.log("onFromComponent2222") },true) } } \ No newline at end of file diff --git a/entry/src/main/ets/workers/Worker.ets b/entry/src/main/ets/workers/Worker.ets index f78f146..15b9d3d 100644 --- a/entry/src/main/ets/workers/Worker.ets +++ b/entry/src/main/ets/workers/Worker.ets @@ -1,5 +1,5 @@ import { ErrorEvent, MessageEvents, ThreadWorkerGlobalScope, worker } from '@kit.ArkTS'; -import { EventPost } from 'EventPost'; +import { EventPost } from 'eventpost'; const workerPort: ThreadWorkerGlobalScope = worker.workerPort; diff --git a/library/BuildProfile.ets b/library/BuildProfile.ets index 653292d..9f4f1d4 100644 --- a/library/BuildProfile.ets +++ b/library/BuildProfile.ets @@ -1,7 +1,7 @@ /** * Use these variables when you tailor your ArkTS code. They must be of the const type. */ -export const HAR_VERSION = '2.0.0'; +export const HAR_VERSION = '2.1.0'; export const BUILD_MODE_NAME = 'debug'; export const DEBUG = true; export const TARGET_NAME = 'default'; diff --git a/library/CHANGELOG.md b/library/CHANGELOG.md index 233305b..0457916 100644 --- a/library/CHANGELOG.md +++ b/library/CHANGELOG.md @@ -1,5 +1,9 @@ # Changelog +## [v2.1.1] 2025.06.14 + +- 底层生命周期感知能力替换成@duke/component-lifecycle库,简化代码,加强可维护性 + ## [v2.1.0] 2025.06.11 - 修复装饰器模式下的多个订阅者下,只有一个订阅者会自动反注册的问题 diff --git a/library/README.md b/library/README.md index 552d13b..5e1a39c 100644 --- a/library/README.md +++ b/library/README.md @@ -1,6 +1,7 @@ # EventPost ## 简介 +[![openHarmony](https://img.shields.io/badge/openharmony-v2.1.1-brightgreen)](https://gitee.com/Duke_Bit/eventpost/releases/tag/v2.1.1) EventPost是一款消息总线,具有生命周期感知能力,支持Sticky。 @@ -127,4 +128,10 @@ DevEco Studio: 5.0.5.315, SDK: HarmonyOS 5.0.1 Release Ohos_sdk_public 5.0.1.115 ## 开源协议 -本项目基于 [MIT license](https://gitee.com/Duke_Bit/eventpost/blob/master/LICENSE) ,请自由地享受和参与开源。 \ No newline at end of file +本项目基于 [MIT license](https://gitee.com/Duke_Bit/eventpost/blob/master/LICENSE) ,请自由地享受和参与开源。 + +## 其他库 + +- @duke/component-lifecycle 鸿蒙版本的Lifecycle库,支持组件、Router和Navigation: [https://gitee.com/Duke_Bit/component-lifecycle](https://gitee.com/Duke_Bit/component-lifecycle) +- @duke/elf-dialog CustomDialog黑魔法 不依赖promptAction 实现的函数级弹窗,省去复杂的模版代码,让你专注于你的业务,一行代码搞定弹窗: [https://gitee.com/Duke_Bit/elf-dialog](https://gitee.com/Duke_Bit/elf-dialog) +- @duke/elf-refresh OpenHarmony 刷新组件,支持下拉刷新和上拉加载更多,支持各种组件,List、Grid,支持header,footer,目标打造HarmonyOS的SmartRefreshLayout: [https://gitee.com/Duke_Bit/ElfRefresh](https://gitee.com/Duke_Bit/ElfRefresh) \ No newline at end of file diff --git a/library/library.har b/library/library.har new file mode 100644 index 0000000000000000000000000000000000000000..cb0affbc33c7a655dcd1340899a06dc0431b3aef GIT binary patch literal 9659 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 { if (!target.rerender) { - hilog.warn(0x0000, 'EventPost', '%{public}s', 'Subscriber current target is not a component') - return + hilog.warn(0x0000, 'EventPost', '%{public}s', 'Subscriber current target is not a component'); + return; } - let onInfo:EventOnInfo = { typeName: TypeName, sticky: sticky ,callBack:propertyDescriptor.value }; - if (target[EVENT_COMPONENT_EVENT_CACHE]) { - target[EVENT_COMPONENT_EVENT_CACHE].set(name, onInfo) - return + if (!target[EVENT_COMPONENT_EVENT_CACHE]) { + let cache = new Array(); + target[EVENT_COMPONENT_EVENT_CACHE] = cache; + cache.push({ + typeName: TypeName, + methodName: name, + sticky: sticky, + callBack: propertyDescriptor.value + }); } - target[EVENT_COMPONENT_EVENT_CACHE] = new Map(); - target[EVENT_COMPONENT_EVENT_CACHE].set(name, onInfo) - let offs = function () { - this[EVENT_COMPONENT_EVENT_CACHE].forEach((info: EventOnInfo, name: string) => { - EventPost.getDefault().off(info.typeName, this[name]); - }) - delete this[EVENT_COMPONENT_EVENT_OFF_HANDLER]; - delete this[EVENT_COMPONENT_EVENT_ON_HANDLER]; - delete this[EVENT_COMPONENT_EVENT_CACHE]; - }; - let ons = function () { - this[EVENT_COMPONENT_EVENT_CACHE].forEach((info: EventOnInfo, name: string) => { - this[name] = function (...args:any[]) { - info.callBack.apply(this, args); - }; - EventPost.getDefault().on(info.typeName, this[name], info.sticky, this); - }) - }; - if (target.aboutToDisappear) { - const oldFunction = target.aboutToDisappear; - target.aboutToDisappear = function () { - this[EVENT_COMPONENT_EVENT_OFF_HANDLER]() - oldFunction.call(this); - }; - } else { - target.aboutToDisappear = function () { - this[EVENT_COMPONENT_EVENT_OFF_HANDLER]() - }; + else { + let cache = target[EVENT_COMPONENT_EVENT_CACHE] as Array; + cache.push({ + typeName: TypeName, + methodName: name, + sticky: sticky, + callBack: propertyDescriptor.value + }); + //不要重复修改原型方向,减少调用堆栈深度 + return; } - if (target.aboutToAppear) { - const oldFunction = target.aboutToAppear; - target.aboutToAppear = function () { - this[EVENT_COMPONENT_EVENT_ON_HANDLER] = ons; - this[EVENT_COMPONENT_EVENT_OFF_HANDLER] = offs; - this[EVENT_COMPONENT_EVENT_ON_HANDLER]() - oldFunction.call(this); - }; - } else { - target.aboutToAppear = function () { - this[EVENT_COMPONENT_EVENT_ON_HANDLER] = ons; - this[EVENT_COMPONENT_EVENT_OFF_HANDLER] = offs; - this[EVENT_COMPONENT_EVENT_ON_HANDLER]() - }; + if (!target[LIFECYCLE_INIT]) { + LifecycleOwner(target, LIFECYCLE_DEFAULT); } - + let oldFunction = target[LIFECYCLE_INIT]; + target[LIFECYCLE_INIT] = function () { + let lifecycle: Lifecycle; + if (!this[LIFECYCLE_DEFAULT]) { + lifecycle = new Lifecycle(); + this[LIFECYCLE_DEFAULT] = lifecycle; + } + else { + lifecycle = this[LIFECYCLE_DEFAULT]; + } + let observer: LifecycleEventObserver = (source, state) => { + if (state == LifecycleState.ON_APPEAR) { + let cache = target[EVENT_COMPONENT_EVENT_CACHE] as Array; + cache.forEach(item => { + source[item.methodName] = (...args) => { + item.callBack.apply(source, args); + }; + EventPost.getDefault().on(item.typeName, source[item.methodName], item.sticky, source); + }); + } + else if (state == LifecycleState.ON_DISAPPEAR) { + let cache = target[EVENT_COMPONENT_EVENT_CACHE] as Array; + cache.forEach(item => { + EventPost.getDefault().off(item.typeName, source[item.methodName]); + }); + } + }; + lifecycle.addObserver(observer); + oldFunction.apply(this); + }; }; } \ No newline at end of file diff --git a/library/src/main/ets/EventOnInfo.ts b/library/src/main/ets/EventOnInfo.ts index f987a83..260ce5f 100644 --- a/library/src/main/ets/EventOnInfo.ts +++ b/library/src/main/ets/EventOnInfo.ts @@ -1,5 +1,6 @@ export interface EventOnInfo { typeName: string - sticky?: boolean - callBack:Function + methodName: string + sticky: boolean + callBack: Function } \ No newline at end of file diff --git a/library/src/main/ets/EventPostExtensions.ts b/library/src/main/ets/EventPostExtensions.ts index f76e17f..6ebca14 100644 --- a/library/src/main/ets/EventPostExtensions.ts +++ b/library/src/main/ets/EventPostExtensions.ts @@ -1,7 +1,10 @@ import { EventPost } from './EventPost' import { hilog } from '@kit.PerformanceAnalysisKit' -import { EVENT_COMPONENT_EVENT_OFF_CACHE, EVENT_COMPONENT_EVENT_OFF_2_HANDLER } from './Constants' +import { Lifecycle, LifecycleOwner, LifecycleState, LIFECYCLE_DEFAULT, LIFECYCLE_INIT } from '@duke/component-lifecycle' +import { EVENT_COMPONENT_EVENT_CACHE } from './Constants' import { EventOnInfo } from './EventOnInfo' +import { systemDateTime } from '@kit.BasicServicesKit' +import { FrameNode, UIContext, uiObserver } from '@kit.ArkUI' EventPost.getDefault().onFromComponent = function (TypeName: string, component: any, callback: Function, sticky: boolean = false) { @@ -9,31 +12,107 @@ EventPost.getDefault().onFromComponent = hilog.warn(0x0000, 'EventPost', '%{public}s', 'onFormComponent component is not a component') return } - this.dispatch.on(TypeName, callback, sticky, component) - let offInfo: EventOnInfo = { typeName: TypeName, callBack: callback } - if (!component[EVENT_COMPONENT_EVENT_OFF_CACHE]) { - component[EVENT_COMPONENT_EVENT_OFF_CACHE] = new Array(); - component[EVENT_COMPONENT_EVENT_OFF_CACHE].push(offInfo) - let offs = function () { - this[EVENT_COMPONENT_EVENT_OFF_CACHE].forEach((info: EventOnInfo) => { - EventPost.getDefault().off(info.typeName, info.callBack); - }) - delete this[EVENT_COMPONENT_EVENT_OFF_CACHE]; - delete this[EVENT_COMPONENT_EVENT_OFF_2_HANDLER]; - }; - component[EVENT_COMPONENT_EVENT_OFF_2_HANDLER] = offs; - if (component.aboutToDisappear) { - const oldFunction = component.aboutToDisappear; - component.aboutToDisappear = function () { - oldFunction.call(this); - this[EVENT_COMPONENT_EVENT_OFF_2_HANDLER]() - }; - } else { - component.aboutToDisappear = function () { - this[EVENT_COMPONENT_EVENT_OFF_2_HANDLER]() - }; + let methodName = `_${systemDateTime.getTime(true)}_${Math.random().toString(36).slice(-8)}` + component[methodName] = callback + if (component[EVENT_COMPONENT_EVENT_CACHE]) { //已经注入过生命周期了 + let cache = component[EVENT_COMPONENT_EVENT_CACHE] as Array + cache.push({ + typeName: TypeName, + methodName: methodName, + sticky, + callBack: callback + }) + let uiContext: UIContext = component.getUIContext() + let uniqueId: number = component.getUniqueId(); + let frameNode: FrameNode = uiContext.getFrameNodeByUniqueId(uniqueId) + if (frameNode) { //aboutToAppear 已经执行完成,加缓存不会自动注册了,需要手动注册 + this.dispatch.on(TypeName, callback, sticky, component) } } else { - component[EVENT_COMPONENT_EVENT_OFF_CACHE].push(offInfo) + this.dispatch.on(TypeName, callback, sticky, component) + let cache = new Array() + component[EVENT_COMPONENT_EVENT_CACHE] = cache + cache.push({ + typeName: TypeName, + methodName: methodName, + sticky, + callBack: callback + }) + if (component[LIFECYCLE_INIT]) { //有生命周期注入,但是没有缓存,则添加缓存 + let keys = Object.keys(component) + for (let i = 0; i < keys.length; i++) { + let property = component[keys[i]] + if (property instanceof Lifecycle) { + property.addObserver((_, state) => { + if (state == LifecycleState.ON_DISAPPEAR) { + let cache = component[EVENT_COMPONENT_EVENT_CACHE] as Array + cache.forEach(item => { + EventPost.getDefault().off(item.typeName, component[item.methodName]); + }) + } + }) + break + } + } + } else { //没有生命周期注入,则添加生命周期 + let lifecycle = new Lifecycle() + lifecycle.addObserver((_, state) => { + if (state == LifecycleState.ON_DISAPPEAR) { + let cache = component[EVENT_COMPONENT_EVENT_CACHE] as Array + cache.forEach(item => { + EventPost.getDefault().off(item.typeName, component[item.methodName]); + }) + } + }) + component[LIFECYCLE_DEFAULT] = lifecycle + let oldAppear = component.aboutToAppear + let oldDidBuild = component.onDidBuild + LifecycleOwner(component, LIFECYCLE_DEFAULT) + //已经错误时机,需要恢复,同时手动注入 + component.aboutToAppear = oldAppear + component[LIFECYCLE_INIT].call(component) + let uiContext: UIContext = component.getUIContext() + let uniqueId: number = component.getUniqueId(); + let frameNode: FrameNode = uiContext.getFrameNodeByUniqueId(uniqueId) + if (frameNode) { //获取到frameNode 已经错过注册事件,需要把didBuild还原 + component.onDidBuild = oldDidBuild + component.lifecycleRegister.call(component) + //需要补充错过的生命周期 + if (lifecycle.isPage) { + let pageInfo = uiContext.getPageInfoByUniqueId(uniqueId) + if (lifecycle.isRouterPage) { + let pageState = pageInfo.routerPageInfo.state + if (pageState == uiObserver.RouterPageState.ON_PAGE_SHOW || + pageState == uiObserver.RouterPageState.ON_BACK_PRESS) { + lifecycle['handler'](LifecycleState.ON_SHOWED) + } else if (pageState == uiObserver.RouterPageState.ON_PAGE_HIDE) { + lifecycle['handler'](LifecycleState.ON_DISAPPEAR) + } + } else if (lifecycle.isNavigation) { + let pageState = pageInfo.navDestinationInfo.state + if (pageState == uiObserver.NavDestinationState.ON_SHOWN || + pageState == uiObserver.NavDestinationState.ON_BACKPRESS) { + lifecycle['handler'](LifecycleState.ON_SHOWED) + } else if (pageState == uiObserver.NavDestinationState.ON_HIDDEN) { + lifecycle['handler'](LifecycleState.ON_DISAPPEAR) + } else if (pageState == uiObserver.NavDestinationState.ON_WILL_SHOW) { + lifecycle['handler'](LifecycleState.ON_WILL_SHOW) + } else if (pageState == uiObserver.NavDestinationState.ON_WILL_HIDE) { + lifecycle['handler'](LifecycleState.ON_WILL_HIDE) + } else if (pageState == uiObserver.NavDestinationState.ON_ACTIVE) { + lifecycle['handler'](LifecycleState.ON_ACTIVE) + } else if (pageState == uiObserver.NavDestinationState.ON_INACTIVE) { + lifecycle['handler'](LifecycleState.ON_INACTIVE) + } + } + } else { + if (frameNode.isVisible()) { + lifecycle['handler'](LifecycleState.ON_SHOWED) + } else { + lifecycle['handler'](LifecycleState.ON_HIDDEN) + } + } + } + } } } \ No newline at end of file -- Gitee From 986513e887315a329249cc59da6a3b44ff6c29fd Mon Sep 17 00:00:00 2001 From: duke Date: Mon, 16 Jun 2025 09:44:40 +0800 Subject: [PATCH 2/2] =?UTF-8?q?build(deps):=20=E6=9B=B4=E6=96=B0=20compone?= =?UTF-8?q?nt-lifecycle=20=E4=BE=9D=E8=B5=96=E7=89=88=E6=9C=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 将 component-lifecycle 依赖版本从本地文件更新为 ^1.0.2 - 更新 HAR_VERSION 从2.1.0 到2.1.1 - 修改 oh-package.json5 和 oh-package-lock.json5 文件中的依赖引用 --- entry/oh-package-lock.json5 | 13 +++++++------ entry/oh-package.json5 | 2 +- library/BuildProfile.ets | 2 +- library/library.har | Bin 9659 -> 0 bytes library/oh-package.json5 | 2 +- 5 files changed, 10 insertions(+), 9 deletions(-) delete mode 100644 library/library.har diff --git a/entry/oh-package-lock.json5 b/entry/oh-package-lock.json5 index ff74946..26e8271 100644 --- a/entry/oh-package-lock.json5 +++ b/entry/oh-package-lock.json5 @@ -5,25 +5,26 @@ "lockfileVersion": 3, "ATTENTION": "THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.", "specifiers": { - "@duke/component-lifecycle@../library/library.har": "@duke/component-lifecycle@../library/library.har", + "@duke/component-lifecycle@^1.0.2": "@duke/component-lifecycle@1.0.2", "eventpost@../library": "eventpost@../library", "libnative_event_post.so@../library/src/main/cpp/types/libeventpost": "libnative_event_post.so@../library/src/main/cpp/types/libeventpost" }, "packages": { - "@duke/component-lifecycle@../library/library.har": { + "@duke/component-lifecycle@1.0.2": { "name": "@duke/component-lifecycle", "version": "1.0.2", - "resolved": "../library/library.har", - "registryType": "local" + "integrity": "sha512-giz0mfwnTzYJ4OfijQv6LAT5uNh8RDRcrwrLjvB6q7KQHFDNXE6lC3gnxOEZjXSs1Npmx0hr2DW9MVJqWueVTA==", + "resolved": "https://ohpm.openharmony.cn/ohpm/@duke/component-lifecycle/-/component-lifecycle-1.0.2.har", + "registryType": "ohpm" }, "eventpost@../library": { "name": "eventpost", - "version": "2.1.0", + "version": "2.1.1", "resolved": "../library", "registryType": "local", "dependencies": { "libnative_event_post.so": "file:./src/main/cpp/types/libeventpost", - "@duke/component-lifecycle": "file:./library.har" + "@duke/component-lifecycle": "^1.0.2" } }, "libnative_event_post.so@../library/src/main/cpp/types/libeventpost": { diff --git a/entry/oh-package.json5 b/entry/oh-package.json5 index 2d5b0c2..23fe0fd 100644 --- a/entry/oh-package.json5 +++ b/entry/oh-package.json5 @@ -7,7 +7,7 @@ "license": "", "dependencies": { 'eventpost': "file:../library", - '@duke/component-lifecycle': "file:../library/library.har" + '@duke/component-lifecycle': "^1.0.2" } } diff --git a/library/BuildProfile.ets b/library/BuildProfile.ets index 9f4f1d4..c822afc 100644 --- a/library/BuildProfile.ets +++ b/library/BuildProfile.ets @@ -1,7 +1,7 @@ /** * Use these variables when you tailor your ArkTS code. They must be of the const type. */ -export const HAR_VERSION = '2.1.0'; +export const HAR_VERSION = '2.1.1'; export const BUILD_MODE_NAME = 'debug'; export const DEBUG = true; export const TARGET_NAME = 'default'; diff --git a/library/library.har b/library/library.har deleted file mode 100644 index cb0affbc33c7a655dcd1340899a06dc0431b3aef..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9659 zcmV;sB}CdEiwFP!000003hjMscvQ!g;JN*hx`mL?!vbSW(E=oeR;wTC2Qre~Ej7@I z)B;JEIK)w3sjs9Ct-hV^D=?A#7ue0b_%4U_9aBgxEp?v%BByCNtmceEE@N z=bQOvc4piUDf@j(HnWp&=i6O-T~)WcZ#NPz;mssbA)#A!s!pAA>YS=mk9#Y`c5h{S zxthlH4$nGQbL%>NzYiX9Fc=J0s}(Nhd#rA(3oj4vFe`E5%hm&Uy#eZ}$ zw*P|+G{#4R#*l?3@q-^k$A%Ik!|_Y+$8LCGR)ckY{Q-QPvt8O+zTN-ETEmJ+26x;@8}M2t=ofK zSeK5YU8pC__oE7ZO(fi1)6e>YHJlKsNoA;bDqnLa8rL>1D71D(xbQYEd`}!1xu-|i zF0jJAi6OZ%5xCd78lP)yc6GWv?hc(K-sD>A*woxH6V66H7!lZ@5W(nvXN~w3hot>C zyBl4ecGp)@$KCDUWU!g2{hMrNgUyD=f3vmLHfR5{4cYc@vYCwrgC!$Ri@O6g`@6Yd zgu_E?BOlrk_V@M)sIt3?jJc?3U@HM_;KKd>NW{+vkw1d^xG>kX1NDa4puqWbs3**E zi0?t&eQdaw(;{i!yICR zKEy^Me7Bz!I3M!y-2?qxP+$dIVUIt+MNp;C$02RISVCJxYVmPwAYbDTA`DEz(00Gj z#}5c7%teH-zZ)abA%CztFyO;fB*6iHzhA5Z7bl!Y@-+gF1|pn}kg7xdywBf*|8j)0 z&_GwfAL-K}pC9Ay8W1=gir_>dMIGj(h7Y3%7YO8Qy7`cwiy*>onm&>VQy;=Y6+|&b zaLV>RzCV)}elSbd&fmia0{nK&T{j=}`7u+GI^1v_ zeH>!D_-!2Fhqi8z7yR8+=%g7!>Bbd7kv=vMKwX?DHO`0pLBvW~3S$aL59wzE2=}(Q z%4}BkgoO1j)ZV(bW3!{ph1~6ELtE>!?j~0g(mL9ayIre8o82AjTQ_x}&5pJGCye-5nl`b!}@Ka-a>4whnjWre;SQ z+OVl@Lus&1^Plq14J;>9FT+g~Z9jJZ1qq!N^m9KGZ>R8{} zhDk(?ts94VE{`XqMJC65rJBN?}AzE=RN5v#uQ%CR`?S>;G^^#6PZ( z9RJ%~j;0pZS1|d%*Z6NVT54<4{=dO!!T!I|WSSfQXB(#T|FL|fp&T{x{UJWc1%;Fk zEl#}?mxrPg2XSP}vMqdw3$ACw{d{o8^Ob#q5Q@~*)cE^*^^rb57w|>&e!ixQ_4RT! zIA|%8MNbJ&y*h?4Vr$=J@f0UTm7oGU{_Ko4# z_g_M7{D8oPQGEC~^03>QxQO5n5*Oh1jgiF3eTif5#$LM_d+lQU^t*{yKaLOWO`O~p zy>&Le_sZ=Xhho=1j_uz&d3j7+v$%47@}skp7ha10_+b3fd7A&Tp_lSC@ncuwhxR5; zU5>%A|ml#Ii3((eZ=PiH~tCI&ma^_LcaV zk7KVNlFZ5yA5FxDUx{D)G>c|h@Ux+pCU3nR9X~~*@e}XGuI`HsUrln4ab?zxqGOj5 zC-=opoteD)atcY39LgDvr757y$47=HKY4d@>_bckku%0}^NrZZVTm}1LPf_8PTss3 zyF4=a{(hX~^?JSe8on>okNkM56$qebd;?p#>C_;ZJ73e9)qpsWQ0&nD>2y=7 z&O)fW#>aO@YPte^S4}?~5x8)T1W{)n8}1y4u)UnV-&d97`sS^~v5S*euEkFr5xLIS z`1`Y`x4Ntucyd;%olzv(r>4V`F-^XE;e5?ADSLX>l$tU}gz!MOfEouP0^e^;<=C08 zLFkz*B2)NKJqmK$(_~Z<_7QeG2ZRpZ5eji^xU#AaZR7nuL~tSEdg@as^sLX9Tmq=9 z=j~B9U_>kXzpF)?=DJf*ML9Z ztE@_5YUBe0{lUtrox5mUzuoT>`YMeEv8=w2!`)gkVOPFpm)N?b-Q!0-h>gCVZg*@( z8C~okiXXoo|IwSVqlb|s45HZn4`QP)q3Ob)h&DbtI(h5rbQ$tBgLT!J;f{oR12A=@ zIq32Yt$K#Fok0};WFq$Jdy^Mlid}hka%lhbRG~1}&u`--#b(5pxG*vG_W66`BLhQP zG*bs&jUW4TCb`i*^p*WnFJGh?Cx5&zK7Lf}Ar9V}IyoBOH#&Ls<;1azxTn8-J$~Yi z*n#oHk*ia0U7k930u83IWss89w$w5v-`_v=!PVH?7co3B@pcMKg_SYPTt1sP`by&D zzR8zw#$G*j2SRGnv^R~PIT;=M^!AP6_?uT_m)^poz?p+|{X05-Wb*Ra#O1ec-x#6# zMT=zW*3bjJ5>xvXVj&82hy5&an9{%c7My&gy}S3T8H0>T{sv!bo>rJ z9*9=d>gjZB*x+)sQ4tuihLMpfHhd~JG5*j(z=$`yo0~h^*SBs)gUFOZ96#}C;{14Q z~QqPNm}amjgi|o4&8;cBq453lG{OKoq-U_@zgtK9){^;MeE&7O)d`= zsttEpXMa5P&bjE=VcK3_MT;h@ZgRJaRxpU{DNUU^HWa_|P^Ojc`DWFfYGJ1W4l1w=wgE{UbsH=I0*PbK~CC0xWf9Kuk*paEX zkH&_HOC39X5exU$Rk~$3_2Hq(D|@GgPEOuBaQntdoTG``=IZ8AyD;GM^L5CgH|Q;T zv(chM?M>gPL!!Ue+D;%w)Fuu^t$lo?GveFYNfrsaDO7JXT2Q59gBv}|g~<||(VQ%i zbQ1AI;pUr(i8tbB_N86pK`fJLCunp8qHsqj)ZQKDLmWco2=@%19*j=BpLlO?{P+Q) zx7RcCb3q}z<9_qL!1jmm+UpFt5z5RT@OOpT@D4QHv@$mS#x&)Sq_m%GLJAQ~T#ca@l)60$FIiU`XF}et@OmAyc|tlJDWIk znes^HUetHLbs%x^V07#fR>vb(qZ1R+n{QH|VCv6<9`|(eJl3*q1fn4(Xk_x9tnNPa{+YIpTnI?h>r;3e8|JkKROhwEFa&$sZpNh57!F;2=8{D0cZw;>cAzk3MiS z{^r%h_=VVw>xmEF!iyWH_r{J)#Lgd%zw=V!5%X!7hK(SnbjiCsQP(cXjm6c2Z2Kb0+u|1j4R<|2I=6YkjX zC-LJ~lglz<14hRV#t)8AQ0(rhStcW8Cmt=x|7eApM!)@{*BNs})8X?5Dv#7_IXP8;Sze8eyC;T_sK?fuN$ zwK{Dd-_K!>_pT*~076{Q#|69nTtr*9bC*sl>R7?TVGWj59R-x=ls9fh6nNg z@cgfz_YDNNh@S20ex!8Vb^JHgnryXq_0NEmd(~AJ~ivWJP5MXd2#c@N#eGve90N^hH;ESvv0|1p+C&oQpy(1cc zV;X?-8h~pWfS+gp{!s%kng?($4>hE zfQAx)<`RI-B>>+o0oYaoFkAv~x&+{dB>bPztc26u?^w@Ny}@tEB+PO96hR0{B)AfGP(-n*-301MnRc zz>6w?<0^n3ssR2<1>jZ!+*ShYRRWAD0amI2oGO5yD*-qqfL;lZr=o3~Z1X?Q1=!fU zaz^ixzIeEj_?1r)tz(po3;?%xESD-9e$G{=pGzdqD^t%5Sn;zAYZb`gi!aux0fuGF zuOG)zrLY1(^{M`Ro z?Ezl!4D@$#;TdxMDRVbY$?>upAJ@YU1caJiF35$kuT&EX^Z5Oi6oeAw4)*YOibWw2 zi$Wq6g+we0iC7dVv0#G(MOrMsrDEBK#iDu~uLR$X_UT`YyOTbpgg&K&KBa^{rG!3Z ziay*qfHFN|MgsI91tc$|l$FOrrm_W<@b_szsuauTMh+zuG{v?5UF>GBDc8-?Y zNn!gitRo4#PGL_jC9qQ&<$gwCPgB@WF^o;ZPM4DUo}jw*KGv<`Buq!kZKibQ<8swW zSQDl5T?%_VqrPv`a{rFP%otXeglQ;@rS<(Ct`A|@;k$Me_wkDCotBp)(d-1b*+oGen(}}@^(EqvE;~NCXq53^(c}==1Pdnl@OULAu=~bB=#jB zH%;V*6@fb!xPW6j>la{&KhoaEhB+VYn_+3cIB0b9VV~Rg0+jU(1iL%296AlKpP8|q!I>dM zSc7iy2n-x%o(ZO==yjfzD<87=gSTdlNYa=OPgd5T0ZTH^%R+G~E&-96VM*pI+)#eU zE8Jl0?Cj-)MmnN92ZFu;ha0@JGZR9aPlWu}Sv1pwkLCLBMqp`Yr*o61soB-(akRKP zJ8?owYtyE5LV0JZrY4F4mZX#1LB9YOWyV+_onpWHGHnZ7MYo8rHyVYbcnyfan-E6j7&8t_>4xiOvHq~0~W{bgUx76B= zMuTxy`0TYdyVYX0*sS)|28-2TvCWRY)poPdV6>X-CVWE0XtW#cmh z;-iOTNxgB9j*$XO(+WZ<%W3BXDA>%gTiduESe)@18|1J)ACyTAM%~Q@0+81oz~HiO z;z<&R9hQos!l_@Ej` z!)!n2;eDKQ$EKkFdjp)?2W7pSfRpfU46N$qQq@TE6q96JB`oUYgiY>7K8VkAkvcZH zQ#@c?sX_&PEOw&8kk{uA@V&6eA4%`mLB2miY-y1{BC)LEv^!m%dTir*{rC_tl=dfU ziomj9hBCN)up%o3OR6d}ZBxicT88iGfigbeTRRXW$7Mmu2ceV?Hu-%{?3O_ud4m8- zC5D!dpD|k@B8W~X4uyGv$9r~=PqxP*P>?jLC0VwyAk2mF_F5R0gj3uS3YVqhB6Uk5 zoX{F<@<&*zDvc!mtUrRc%^YElb%a7;{sn(OD3~12PTSdV5UOWzryiLH zm@;YX0XpvKYgNzSGF8vu`Bcx~z^t0y4_P(6JF#kduVB^mgZrxK$LK{FXX;bqw! zqeR&=d>v8a^5Ne<^7hD>>*L0`@ZkNtWY(rHH`ZELTUO(? zS#7ShTJiphjWp1-=^s6Eh6piao{?Te1-v3D2Y|QL0RN;0Fl22PO8#nF~~Hi0LSHW2dn`WK3CU5Lk-vf zSZ243m3^*ez$`hn!&X<~YFyg)(Tx z+a=x{r~DgVmfEdgna|bD;ANc3d~oJG1_f$ptyojYk}5TsRn9A=Rn7;Q=QQKZaTaFb zD9Q(C$pR>NOoF2<6UU+j6vtwadA^BpEXl&LG#{MH7D7R}1jq7B94i-69F-vRlwcfR z%fg|{2dBOa3Jek)#!MXMGK#|jGSAPjbZl8TR_BBBsrgV)FTv4}iQ}316o(UJoqj8?8_0JYq!s4w&?>ycMgPZYKROJ)t&0T>dsf=!0& zRjdS-F{?HLLj;urGK}HrJ8Z+NTE4MFY9Lr!TZ$wp3Q_k|7==Q9h9R`8u&u0;fy%3L zDs)h-Qej-qTs>54RIIGQ0k(N6Rt^R8<*jA1#sU+7tZ{)EV9f$uF)*^0Z{jSaII9h8 zWwPZP*U1_ekz9+70Be>}97|NJ9A{W6XXRd*ZkZeyOnG^xI;;>?y8@HQ$d`au?gR@| z%j8%lVtXoX(>+mB|a1%2=6Kw*1t2NWmBYvC5PNd1cO3Mp%AoALhIIYeYECnhK~kV)D&;sJ399WO^Gg&ee9T zL0VSER6Iq2AKgWpwSDQfLRruy9Cm7r? zh4tVqaKc(B->8(e$mPp7KDAqp+tGmek+on824H0kxxmUB@_I=>J8vq*TKLG_T^UQ^90F4Wt zfC6*zW`M>L3lw+@oR8Iu1s2vrJu*N3EI{MpdMIeg_ZB#pSfFufJrn@PD2j;YS&88< z0lfkgz$ukMP&3}#dSZJ|!(w2WrsAe!xr|KSC~p9g+>q75DK%iv0fvBTuqCV8fw5~+ zDYki;`R5l<3n(N;s%ikW!kbeM-rV{^ueu(Yp%s{V1JQ4$8mi@(Lgkuiy22dNW(rj^ z#Zc(Yr556Zui@@c?NqFTdN8XxQ}}YKp<0dc@AGx6mUd?3%kEZRWkQ_3TtmYd-@ zkPR|sW(&yb!7TeW$m@|={yfO*3qvee6yF5$RWnSc6QeB$Rt8wBYIDAWElz%ektuLA z_glccsD2U{FH@Vx0`uZL7kQrV1$eQb2^cT&3lxga8L{)z0#gBiHJt&h>CmFVYV`~q z?-kELp(-`r=VT2m>P6tpD}jQ1$@n%uvndM2@xCZIzLjL*cx(|k7ZyXo zVxPNI9N(5@p(tMj&J}7Xs7Q`)mDPal9GtqkX&ONWOeKm#wqQMV+M{mrU^) z0}UErf!Y`2W$d8DDR!BXX(+$|CJ9g|p`ifmDkamf5CddMK&}!R7J^-)WEx5_K%NB5 zQ{vMt_W4StVLk>Zl7K=bG|UHkk&;n91`Ze&b^*(jZ_H7!%piE- zYYYRNI**)fDggPo8^z zxoerH6zaU+&}96xfGL{cmzEUZ$!n{Cd36tSm|?aqU6J~?d}+nM>}C!#N?g$hQzYis zlA4MZls(5(sH z!~8wut|eINukT@gim|-7_2W-I+q(5_X2I62DKh7iJPQ^-+086ftMg8X$t{$ckM=M> z0}ZL@K0S0+_Kq3yL+1@-FRRegXM!GlaIn_-^JD1B5n$ z^0AEK1=m)A>c2qQ;v((YJ}E!pf+V)AY#5p5pP(pb ze#Ph><~LBN&f5yd8IWV1Xc=64BO@z}{NyJYMGLR3f+vqMCCV4oFV6d(;@7*2h<;6@ zMzmBnVO+}Jj~a9WhdXSP{EHO;6)ORrUJ1~@65zF!02fyRe6|wcpH~7jRRHu? z0K8rSFkS)hpDF-;TXC29?_9X=AU*$0mTkU*Iv)J|cdgkn_x|Us!-Jgv&RDj4#B@A( z`&*0_(_H({Hat}O)00i)CBR2T$35QvGa01k|1Bo`{RfM=cJBQDY{T^5e=ud_*{M-$ z*-%JZhjwbzYHe5Q=#;h&Y5lw&ulA=u(W%wpOyav|h`xM=Q^Xep@e6F)I%K3WkV29e z$z?tiOTRzp*x*jRV1_KBHV`1)SH1&oF&J$G&W8Nr7qsYmXh(y;m>@54Qc5| zyo^>$cAg{($-8W{j*u(3%^&82_#%RcwhnE1UY8b9vJ{q{nCuVW1A-(~+)LDI)Vp*V zwU$~{Qp!P58sgWoXmLTr*T;sFV&3NOCe@I-HENPZwwy=?ETyghmyDSFL8JKC&4#ra zwVF~ZT6nSr?(&`|&Mkh3mu$GM4Rc&(GyB8B02^pwyZih>%6xdM(L}bG3>i{Qih+xW zoQoVuUz$W)p4X^%Y35!M{9T4S`v0)_A)rU-1w8opZ#CPDbL0PP!$bRj>64+4HuK!~|7RT@;QlZAnm9+koh@WtnT6_+HuDU!HhsU=Oa+s7Yh{!bk2Gul zfbY}#eGAjtfBIa|{|Eaw8fuMq*uT{>_x|s!!~NL*ofim9dvTvuKf~dq`?-WbpLGss zn(m`VJj<8$74=Fw52(X;iRln_o9ht$Vx4%Cz%(6EfQ>{X_hg74^QYGdAn`!w8lGI8 z)$kMrhQj`BnBepYMG+u9-dKmacs{_f!4xcgAo5PwbS3afS?S?Vd>uljWW z&FW@op|l`y$;^|B4_uhcSt`@1yXHFTKk#t({y*~^;=>LG_wfHrCRA?fHzsX?3`+sxoKfCZK z+n;<3{vmgT@3sDG7WaQmCS$GDQVZm!@;U#1*5Qu(-$nUK!%huCTGF^=j}Z@_JH>kx zQ`?l&+yJ1}B{OYf0|O+N#n2Pd(n}RJ2t7ZyulIWq?$`e5s@ubL0Qa*0T0^$|n~i3} xoc+%>+_(MH#=S=efNuwx#_TbSt`&%?G}i~rg}E>n=ECno_