组件复用提升性能,不小心可能踩的坑,注意避让

组件复用提升性能,不小心可能踩的坑,注意避让

HarmonyOS
2024-06-11 20:45:13
1802浏览
收藏 0
回答 1
回答 1
按赞同
/
按时间
沉默如海

组件复用可以大大提升应用的帧率性能。但是如果使用不小心,可能会引入功能问题。

遇到的问题:组件复用后,应用列表中按钮的状态出现了错乱。比如页面中的按钮状态本来应该是“打开”,因为这个应用已经安装了,但是却显示成了“安装”。

问题分析:

1:问题是出现在组件复用之后,所以怀疑组件复用导致的问题。

2:分析布局结构:应用布局结构是一个NoralCard自定义组件,且是一个复用单元。

并且通过日志观察,应用的组件是复用过的,并且是复用了另外一个未安装的应用。 页面上其他元素如:ICON,应用名称等都是正确,只有按钮状态不符合预期,于是分析代码发现:安装按钮也是应用自定义的一个组件(DownloadButton),也就是DownloadButton是NormalCard的子组件。

3:代码分析:NormalCard中的引用子组件DonwloadButton的代码如下:

export struct NormalCard { 
  @State private cardData: NormalCardData | undefined = undefined; 
  ... 
  Row() { 
    DownloadButton({ 
      inDetailPage: false, 
      appInfo: this.cardData, 
      constraintSizeOptions: this.constraintSizeOptions, 
      fontSize: $r('sys.float.ohos_id_text_size_button3'), 
      fontColor: $r('sys.color.ohos_id_color_text_primary_activated'), 
      defaultBackgroundColor: $r('sys.color.ohos_id_color_button_normal') 
    }) 
  } 
  ... 
} 
 
export struct DownloadButton { 
  ... 
  private appInfo: NormalCardData; 
  ... 
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.

如组件复用指导中所提:父组件中cardData增加了状态变量,cardData变化之后,相应的组件会自动刷新。但是由于DownloadButton是自定义组件,DownloadButton接收cardData的变量appInfo是一个普通变量,没有支持父子组件数据传递的状态变量。因此即使父组件中cardData数据变化了,也没有传递给子子组件DownloadButton。

4:修改方案:将子组件DownloadButton中接收父组件数据变化的成员变量:appInfo增加数据同步的状态变量:@Link,同时增减监听事件,变化之后,需要根据appInfo刷新按钮的状态。

export struct DownloadButton { 
  ... 
  @Link @Watch("updateUiWithReuse") appInfo: NormalCardData; 
  ... 
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.

5:修改过程中数据同步遇到的问题:一开始考虑业务只需要单向同步:用的@Prop。但是用@Prop之后丢帧更严重中了。通过trace发现。数据同步过程中有大量的数据copy。且由于NormalCardData数据类型嵌套较深,且@Prop是深度copy,导致性能特别差:复用占用了33ms。如下图所示:

6:继续优化:通过与OH 数据同步的同事了解,@Prop是通过数据深度copy完成的数据同步,他们建议如果数据大可以使用@Link进行数据同步,@Link是通过指向同一份地址的方式完成数据同步。修改为@link后,复用效果大大提升。由33MS->2.9MS ,性能有10倍提升。

总结:

1:组件复用要考虑组件中所有元素数据是否都进行了合理的刷新,如果涉及自定义组件,自定义组件涉及的UX变更需要通过数据同步的方式,通知子组件变更,子组件需要根据父组件数据通知的变化,完成本身的UX刷新。

2: 数据同步过程需要根据自己的应用场景选择合适的数据同步状态变量。特别注意@Prob@Link。 @Prop为深度copy的方式,@Link是通过共享数据内存的方式。性能差异较大。

分享
微博
QQ
微信
回复
2024-06-12 17:46:47


相关问题
性能优化中组件复用原理是什么
3092浏览 • 1回复 待解决
HarmonyOS NDK JSBridge是否有性能提升
801浏览 • 1回复 待解决
HarmonyOS 组件复用问题
1291浏览 • 1回复 待解决
HarmonyOS Web组件安全避让导航栏
915浏览 • 1回复 待解决