HarmonyOS Next IM Combat: Functional Anomaly of Event Cancellation Caused by Dual Navigation Lifecycles
Background Introduction
Users of the IM application's chat page reported being unable to view large images by clicking on them. Code review showed that the large image click used the ohos.events.emitter
event mechanism. Further investigation revealed that events were emitted but not consumed. Logs indicated successful event registration, but no event reception.
Problem Diagnosis
Further analysis showed the issue consistently occurred when cold-starting the app by clicking a notification, while hot-starting via a push notification worked normally. Both company apps integrated HarmonyOS's PushKit to receive notifications when backgrounded or closed, but only one exhibited the problem.
Log analysis revealed that cold-starting the app from a notification and entering the chat page triggered one aboutToAppear
and one proactive aboutToDisappear
in the chat page. Further inspection showed the chat page's lifecycle was executed twice: Chat Page 1 aboutToAppear
→ Chat Page 2 aboutToAppear
→ Chat Page 2 aboutToDisappear
.
Initially suspected to relate to PushKit, the hypothesis was dismissed when the other app functioned normally. Clicking a notification triggers navigation to the chat page via onNewWant
. Expert consultation suggested the issue might stem from multiple Navigation
instances in the app.
Code review revealed that after a cold start, the app did not immediately navigate to the chat page in onNewWant
but waited for the home page to load, then navigated to the chat page in the home page's aboutToAppear
. The app loads a splash screen in onWindowStageCreate
, navigates from the splash screen's aboutToAppear
to the home page, and then from the home page's aboutToAppear
to the chat page. The splash screen and home page are two Navigation
instances sharing a NavPathStack
.
Understanding Navigation
lifecycles: As a routing container, Navigation
lifecycles are hosted on NavDestination
components, exposed as component events. Lifecycles fall into three categories: custom component lifecycles, universal component lifecycles, and proprietary lifecycles. aboutToAppear
and aboutToDisappear
are custom component lifecycles (for the custom component wrapping NavDestination
), while onAppear
and onDisappear
are universal component lifecycles. The remaining lifecycles are unique to NavDestination
.
-
aboutToAppear: Executed after creating a custom component and before its
build()
function (beforeNavDestination
creation). Allows modifying state variables, which take effect in the subsequentbuild()
execution. -
onWillAppear: Executed after
NavDestination
creation and before mounting to the component tree. State changes here take effect in the current frame. -
onAppear: Universal lifecycle event triggered when
NavDestination
mounts to the component tree. -
onWillShow: Executed before
NavDestination
is layout-displayed (not triggered when the app switches to the foreground). -
onShown: Executed after
NavDestination
is layout-displayed, indicating layout completion. -
onActive: Triggered when
NavDestination
is active (at the stack top and operable, with no special components obscuring it). -
onWillHide: Executed before
NavDestination
is hidden (not triggered when the app switches to the background). -
onInactive: Triggered when
NavDestination
is inactive (not at the stack top or obscured by special components when at the stack top). -
onHidden: Executed after
NavDestination
is hidden (when a new page is pushed, the top page is popped, or the app switches to the background). -
onWillDisappear: Executed before
NavDestination
is destroyed. If there is a transition animation, it triggers before the animation (when the top page is popped). -
onDisappear: Universal lifecycle event triggered when
NavDestination
is unmounted and destroyed from the component tree. - aboutToDisappear: Executed before a custom component is destructed; state variable modifications are prohibited.
The lifecycle when navigating from Page A to Page B is: A aboutToAppear
→ B aboutToAppear
→ A aboutToDisappear
.
The root cause was identified: When navigating to the chat page in the home page's aboutToAppear
, the splash screen's aboutToDisappear
had not completed, leaving both Navigation
instances active. This caused the chat page to execute aboutToAppear
twice. After the splash screen's aboutToDisappear
, the second chat page instance was automatically aboutToDisappear
ed, canceling event subscriptions.
Solution
After identifying the problem, the fix involved adding a 20ms delay to the chat page navigation, resolving the issue. A more elegant solution is to navigate to the chat page after the splash screen's aboutDisappear
or modify the splash screen to a non-Navigation
structure.
Summary
Step-by-step troubleshooting revealed the root cause: Cold-starting the app with two Navigation
components (splash screen and home page) sharing a NavPathStack
caused the chat page to be repeatedly created and destroyed when navigating from the home page's aboutToAppear
before the splash screen's aboutToDisappear
completed. This invalidated event subscriptions (as the second page instance did not register event consumption logic). Solutions include delaying navigation, adjusting navigation timing until the splash screen is destroyed, or restructuring the splash screen as a non-Navigation
to eliminate multi-Navigation
coexistence. This case highlights the complexity of Navigation
lifecycle management in HarmonyOS, emphasizing the need to strictly follow component mounting/unmounting order in multi-page navigation to avoid lifecycle conflicts.
Reference: Component Navigation (Navigation) (Recommended): https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/arkts-navigation-navigation#%E9%A1%B5%E9%9D%A2%E7%94%9F%E5%91%BD%E5%91%A8%E6%9C%9F
Top comments (0)