HarmonyOS鸿蒙Next中有关 freezeWhenInactive 和 @watch 之间的疑问

发布于 1周前 作者 songsunli 来自 鸿蒙OS

HarmonyOS鸿蒙Next中有关 freezeWhenInactive 和 @watch 之间的疑问 摘录文档内容如下 (链接 https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V13/arkts-custom-components-freeze-V13#navigation)

具体流程如下:

  1. 点击change flag,改变flag为false:

    • 被标记@Reusable的ChildComponent组件在下树时,不会被销毁,而是进入复用池,触发aboutToRecycle生命周期,同时设置状态为inactive。
    • ChildComponent同时也开启了组件冻结,当其状态为inactive时,不会响应任何状态变量变化带来的UI刷新。
  2. 点击change desc,触发Page的成员变量desc的变化。

    • desc是@State装饰的,其变化会通知给其子组件ChildComponent@Link装饰的desc。
    • 但因为ChildComponent是inactive状态,且开启了组件冻结,所以这次变化并不会触发@Watch(‘descChange’)的回调,以及ChildComponentUI刷新。如果没有开启组件冻结,当前@Watch(‘descChange’)会立即回调,且复用池内的ChildComponent组件也会对应刷新。
  3. 再次点击change flag,改变flag为true:

    • ChildComponent从复用池中重新加入到组件树上。
    • 回调aboutToReuse生命周期,将当前最新的count值同步给子组件。desc是通过@State->@Link同步的,所以无需开发者手动在aboutToReuse中赋值。
    • 设置ChildComponent为active状态,并且刷新在inactive时没有刷新的组件,在当前例子中,就是Text(ChildComponent desc: ${this.desc})。

我的问题是,第三步 (再次点击change flag,改变flag为true时),由于恢复了被冻结的变量,为什么@Watch(‘descChange’)不会被调用?

相关代码如下:

[@Reusable](/user/Reusable)
@Component({freezeWhenInactive: true})
struct ChildComponent {
  @StorageLink('desc') [@Watch](/user/Watch)('descChange') desc: string = '';
  [@State](/user/State) count: number = 0;

  descChange() {
    console.info(`ChildComponent messageChange ${this.desc}`);
  }

  aboutToReuse(params: Record<string, ESObject>): void {
    this.count = params.count as number;
  }

  aboutToRecycle(): void {
    console.info(`ChildComponent has been recycled`);
  }

  build() {
    Column() {
      Text(`ChildComponent desc: ${this.desc}`)
        .fontSize(20)
      Text(`ChildComponent count ${this.count}`)
        .fontSize(20)
    }.border({width: 2, color: Color.Pink})
  }
}

@Entry
@Component
struct Page {
  @StorageLink('desc') desc: string = 'Hello World';
  [@State](/user/State) flag: boolean = true;
  [@State](/user/State) count: number = 0;
  build() {
    Column() {
      Button(`change desc`).onClick(() => {
        this.desc += '!';
      })
      Button(`change flag`).onClick(() => {
        this.count++;
        this.flag =! this.flag;
      })
      if (this.flag) {
        ChildComponent({count: this.count})
      }
    }
    .height('100%')
  }
}

更多关于HarmonyOS鸿蒙Next中有关 freezeWhenInactive 和 @watch 之间的疑问的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html

5 回复

我的理解是@Watch只能观察处于活动状态页面,第三次将flag设置为true而且你的desc也发生了变化,但是变化是发生在页面不活动状态,这个时候watch是不处于观察状态的(freezeWhenInactive为true的效果),flag设置为true该page会重新激活且重新注册监听,默认值就是修改后的值,因此不会触发desChange函数的监听调用。而去掉freezeWhenInactive这个属性的后就会发现页面隐藏后@watch的函数依然会触发,这种就属于不移除监听,只要值发生变化就会调用监听的函数。

更多关于HarmonyOS鸿蒙Next中有关 freezeWhenInactive 和 @watch 之间的疑问的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


但是 https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V13/arkts-custom-components-freeze-V13 中的 TabContent 案例和 LazyForEach 案例, 我试了下,都是切回 active 时,触发 @watch 回调。很好奇~,

你说的这两个案例都是存在没有被freeze的@watch,因此总是能够监听到变化,你可以打印下被freeze的component是否可以监听到变化从而触发监听函数。你的这个案例里是通过flag来显示和隐藏这一个可以被回收再利用的控件,因此被冻结后再利用很明显就不会触发监听函数调用,只有后续再变更desc的值才会触发。

在HarmonyOS鸿蒙Next中,freezeWhenInactive@watch 是两个不同的特性,分别用于不同的场景。

freezeWhenInactive 是一个组件属性,用于控制组件在非活跃状态时是否冻结。当组件处于非活跃状态(如页面切换、后台运行等),设置 freezeWhenInactivetrue 时,组件会被冻结,以减少资源消耗。默认情况下,该属性为 false,即组件在非活跃状态下仍然保持运行。

@watch 是一个装饰器,用于监听数据的变化。当被 @watch 装饰的变量发生变化时,系统会自动触发相应的回调函数。这在数据驱动的UI更新中非常有用,可以确保UI与数据保持同步。

两者之间没有直接的关联,freezeWhenInactive 主要关注组件的生命周期和资源管理,而 @watch 则关注数据变化时的响应机制。在使用时,可以根据具体需求分别配置它们。

在HarmonyOS鸿蒙Next中,freezeWhenInactive@watch是用于管理组件状态和响应的两个不同机制。

freezeWhenInactive用于控制组件在非活动状态时是否冻结其状态,以减少资源消耗。当组件不再活跃时,系统会冻结其状态,避免不必要的计算和渲染。

@watch则是一个装饰器,用于监听某个状态变量的变化,并在变化时自动执行相应的回调函数。它通常用于响应式编程中,确保界面或逻辑与数据状态保持同步。

两者可以结合使用,@watch监听状态变化,而freezeWhenInactive确保在非活动状态下不进行不必要的处理。

回到顶部
AI 助手
你好,我是IT营的 AI 助手
您可以尝试点击下方的快捷入口开启体验!