HarmonyOS 鸿蒙Next中Navigation系列五:Navigation生命周期管理

HarmonyOS 鸿蒙Next中Navigation系列五:Navigation生命周期管理

1、Navigation生命周期管理原理

Navigation作为路由容器,其生命周期承载在NavDestination组件上,以组件事件的形式开放。其生命周期大致可分为三类,自定义组件生命周期、通用组件生命周期和自有生命周期。

自定义组件生命周期函数

其中,aboutToAppear和aboutToDisappear是自定义组件的生命周期(NavDestination外层包含的自定义组件),由于NavDestination的页面依赖自定义组件builder去构造,所以这两个生命周期也可以被开发者使用,但这两个生命周期实际上是在NavDestination页面创建导销毁的完整生命周期之外的,所以也会存在一些限制和差异,如:无法通过NavDestination的无感监听感知、在aboutToAppear中做栈操作会跟上一次栈操作合并成一次等。

- aboutToAppear

在创建自定义组件后,执行其build()函数之前执行(NavDestination创建之前),不建议在这里做栈操作。

- aboutToDisappear

自定义组件析构销毁之前执行,不允许在该方法中改变状态变量。

通用组件生命周期函数

OnAppear和OnDisappear是组件的通用生命周期,为NavDestination组件上下UI树时触发。

- onAppear

通用生命周期事件,NavDestination组件挂载到组件树时执行。

- onDisappear

通用生命周期事件,NavDestination组件从组件树上卸载时执行。

NavDestination独有生命周期:

- onWillAppear

NavDestination创建后,挂载到组件树之前执行,在该方法中更改状态变量会在当前帧显示生效。

- onWillShow

NavDestination组件布局显示之前执行,此时页面不可见(应用切换到前台不会触发)。

- onShown

NavDestination组件布局显示之后执行,此时页面已完成布局。

- onActive

NavDestination处于激活态(处于栈顶可操作,且上层无特殊组件遮挡)触发。

- onWillHide

NavDestination组件触发隐藏之前执行(应用切换到后台不会触发)。

- onInactive

NavDestination组件处于非激活态(处于非栈顶不可操作,或处于栈顶时上层有特殊组件(全局弹窗、模态、OverlayManager)遮挡)触发。

- onHidden

NavDestination组件触发隐藏后执行(非栈顶页面push进栈,栈顶页面pop出栈或应用切换到后台)。

- onWillDisappear

NavDestination组件即将销毁之前执行,如果有转场动画,会在动画前触发(栈顶页面pop出栈)。

特殊的生命周期:

除了以上介绍的常规生命周期外,Navdestination还具备两个特殊的生命周期:

- onNewParam

该生命周期会在Navdestination通过单例跳转再次回到栈顶时触发,并接收到新的param参数。

- onResult

该生命周期会在Navdestination通过back事件或pop操作回到栈顶时触发,如果是其他Navdestination通过pop携带返回参数回到栈顶时,onResult会接收到返回参数。

整体生命周期时序可以参考下图所示:

按照状态的切换流图如下:

2、生命周期用法示例

上一节中讲解了Navigation路由框架生命周期的原理。开发者可以在对应的生命周期中增加逻辑,当路由操作触发对应的生命周期后,逻辑会对应的执行。本节将会通过页面跳转与半模态激活的功能,来演示两对常用的生命周期:onShown、onHidden 和 onActive、onInActive。

首先,定义如下的半模态

// LifecycleNavDest.ets

// 用以拉起一个半模态
@Builder
function sheetBuilder() {
  SheetDemo()
}
@Component
struct SheetDemo {
  build() {
    Column() {
      Text('半模态示例')
    }
    .width('100%')
    .height('100%')
  }
}

如下的示例演示了通过路由push操作,与激活、隐藏半模态来触发这两组生命周期的行为:

// LifecycleNavDest.ets

@Component
struct LifecycleNavDestination {
  name: string = 'NA'
  stack: NavPathStack = new NavPathStack()

  @State isActive_: boolean = false;
  @State isOnShown_: boolean = false;
  @State showSheet_: boolean = false;

  build() {
    NavDestination() {
      Button() {
        // 根据@State修饰的变量isOnShown_来更新显示的内容
        Text('当前页面的active状态: ' + (this.isActive_ ? 'onActive' : 'onInActive'))
          .fontColor(this.isActive_ ? Color.White : undefined)
      }
      .height(42)
      .width(330)
      .margin(7)
      .backgroundColor(this.isActive_ ? '# 0cc' : '# ccc')
      Button() {
        // 根据@State修饰的变量isActive_来更新显示的内容
        Text('当前页面的show状态: ' + (this.isOnShown_ ? 'onShown' : 'onHidden'))
          .fontColor(this.isOnShown_ ? Color.White : undefined)
      }
      .height(42)
      .width(330)
      .margin(7)
      .backgroundColor(this.isOnShown_ ? '# 0cc' : '# ccc')
      Button('跳转到pageOne')
        .width(330)
        .margin(7)
        .onClick(() => {
          // 发生了页面跳转,会触发当前页面的onInActive和onHidden
          this.stack.pushPath({name: 'lifecyclePageOne'})
        })
      Button('开启半模态')
        .width(330)
        .margin(7)
        .onClick(() => {
          // 拉起一个半模态页面,当前NavDestination页面仍然可见,因此不会触发onHidden。但会触发onInActive
          this.showSheet_ = !this.showSheet_;
        })
        .bindSheet($$this.showSheet_, sheetBuilder(), {
          detents: [SheetSize.MEDIUM, SheetSize.LARGE, 600],
          preferType: SheetType.BOTTOM,
        })
    }
    .onReady((context: NavDestinationContext) => {
      console.log('AceNavigation', 'LifecycleNavDestination', 'onReady')
      // 在onReady回调中获取NavPathStack实例
      this.stack = context.pathStack
    })
    .onShown(() => {
      console.log('AceNavigation', 'LifecycleNavDestination', 'onShown')
      // 在onShown生命周期触发时,修改状态变量isOnShown_为true
      this.isOnShown_ = true;
    })
    .onHidden(() => {
      console.log('AceNavigation', 'LifecycleNavDestination', 'onHidden')
      // 在onHidden生命周期触发时,修改状态变量isOnShown_为false
      this.isOnShown_ = false;
    })
    .onActive(() => {
      console.log('AceNavigation', 'LifecycleNavDestination', 'onActive')
      // 在onActive生命周期触发时,修改状态变量isActive_为true
      this.isActive_ = true;
    })
    .onInactive(() => {
      console.log('AceNavigation', 'LifecycleNavDestination', 'onInactive')
      // 在onActive生命周期触发时,修改状态变量isActive_为false
      this.isActive_ = false;
    })
  }
}

可以看到,当进行push操作后,active与onshown会同时触发(对应于页面中上两个按钮置灰);当进行拉起半模态操作后,仅有active按钮会被置灰(表示当前NavDestination可见但不处于Active状态)。


更多关于HarmonyOS 鸿蒙Next中Navigation系列五:Navigation生命周期管理的实战教程也可以访问 https://www.itying.com/category-93-b0.html

2 回复

在HarmonyOS Next中,Navigation的生命周期管理主要涉及页面栈导航时的状态变化。当使用Navigation组件时,页面会经历onPageShow、onPageHide等生命周期回调。push新页面时,原页面触发onPageHide,新页面触发onPageShow;pop返回时,当前页触发onPageHide,目标页触发onPageShow。页面销毁时会调用aboutToDisappear。这些回调可用于资源释放或数据加载。Navigation通过路由机制自动管理页面栈,开发者无需手动处理栈关系。

更多关于HarmonyOS 鸿蒙Next中Navigation系列五:Navigation生命周期管理的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


在HarmonyOS Next中,Navigation的生命周期管理确实非常精细。从您的描述来看,NavDestination的生命周期可以分为三类:自定义组件生命周期、通用组件生命周期和自有生命周期。

关于自定义组件生命周期(aboutToAppear/aboutToDisappear)需要注意:

  1. 这两个生命周期是在NavDestination创建/销毁之外触发的
  2. aboutToAppear中不建议做栈操作
  3. aboutToDisappear中不允许改变状态变量

通用组件生命周期(onAppear/onDisappear)是标准的组件挂载/卸载事件。

NavDestination特有的生命周期非常丰富,包括:

  • 显示相关:onWillAppear/onShown/onWillShow
  • 隐藏相关:onWillHide/onHidden
  • 激活状态:onActive/onInactive
  • 销毁相关:onWillDisappear

特殊生命周期onNewParam和onResult为参数传递场景提供了便利。

示例代码很好地展示了如何使用onShown/onHidden和onActive/onInactive这两组生命周期来管理页面状态。通过半模态和页面跳转的场景,清晰演示了不同操作触发的生命周期变化。

建议开发者根据实际业务需求,在合适的生命周期中执行相应逻辑。例如:

  • 数据加载可以放在onWillAppear中
  • 资源释放可以放在onWillDisappear中
  • 状态恢复可以放在onResult中

生命周期时序图和状态切换图非常有助于理解各生命周期的触发时机。

回到顶部