HarmonyOS鸿蒙Next中如何解决Canvas画板绘制多条路径时缩放过程中出现的APP闪退

HarmonyOS鸿蒙Next中如何解决Canvas画板绘制多条路径时缩放过程中出现的APP闪退

【问题现象】

使用离屏画布画出线条进行缩放时,发生APP闪退,没有堆栈信息。

【背景知识】

使用Canvas组件或Canvas API时,渲染、动画和用户交互通常发生在应用程序的主线程上,与画布动画和渲染相关的计算可能会影响应用程序性能。OffscreenCanvas提供了一个可以在屏幕外渲染的画布,这样可以在单独的线程中运行一些任务,从而避免影响应用程序主线程性能。

【定位思路】

  1. APP发生闪退一般是由Crash和内存溢出引起,由于没有堆栈信息,先排查是否发生内存溢出。通过DevEco Studio自带的profile工具,发现Canvas缩放过程中,该应用的内存占用一直在往上涨,并且长时间无法释放,直到APP闪退,如图所示内存占用1.6G。

    点击放大

  2. 查看缩放代码,离屏画布的大小会被修改,且调用次数频繁,最终导致内存不断变大。

【解决方案】

  1. 在手势缩放事件发生时,设置阈值,减少缩放变化次数,进而减少画布重绘次数。

    // 变化量超过阈值,才会促发更新
    .gesture(
      PanGesture()
      ... 
      .onActionUpdate((event: GestureEvent) => {
         if (Math.abs(offsetX - this.lastOffsetX) < 0.5 && Math.abs(offsetY - this.lastOffsetY) < 0.5) {
           return;
         }
         this.lastOffsetX = offsetX
         this.lastOffsetY = offsetY
         // 计算height
         ...
         })
      ... 
    )
    
  2. 使用Canvas组件替换离屏画布。

    build() {
      Column() {
        Column() {
          Column() {
            Canvas(this.context).width('100%').height('100%')
              .onReady(() => {
                this.context.canvas.scale(this.height / 100, this.height / 100)
                this.context.canvas.drawLine(50, 50, 160, 160)
                this.context.invalidate()
              })
          }
          .border({ width: 2, color: "# 66F1CCB8" }) // 边框,仅用于展示效果
        }
        .backgroundColor("# FFFFFF")
        .height(this.height)
        .width(this.height)
        .justifyContent(FlexAlign.Center)
        .alignItems(HorizontalAlign.Center)
        ...
      }
    }
    

    修改后结果:

    DevEco Studio内存检查显示不会飙升,没发生APP闪退现象。

    点击放大

【总结】

Canvas的宽高变化会导致重绘,频繁变化会导致离屏画布的内存占用变多,进而引发APP闪退,缩放场景可以使用Canvas替换。


更多关于HarmonyOS鸿蒙Next中如何解决Canvas画板绘制多条路径时缩放过程中出现的APP闪退的实战教程也可以访问 https://www.itying.com/category-93-b0.html

1 回复

更多关于HarmonyOS鸿蒙Next中如何解决Canvas画板绘制多条路径时缩放过程中出现的APP闪退的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


在HarmonyOS鸿蒙Next中,解决Canvas画板绘制多条路径时缩放过程中出现的APP闪退问题,可以采取以下两种方法:

  1. 设置缩放阈值:在手势缩放事件中,设置变化量阈值,减少缩放变化次数,从而降低画布重绘频率。例如,仅当偏移量变化超过0.5时才触发更新。

  2. 替换离屏画布为Canvas组件:直接使用Canvas组件代替离屏画布,避免频繁修改离屏画布大小导致的内存占用问题。确保Canvas的宽高变化不会引发频繁重绘。

修改后,DevEco Studio内存检查显示内存占用稳定,APP闪退问题得到解决。

回到顶部