uni-app重新渲染video时内存一直上涨直至闪退 android app-vue

发布于 1周前 作者 htzhanglong 来自 Uni-App

uni-app重新渲染video时内存一直上涨直至闪退 android app-vue

操作步骤

关键代码:

mounted() {  
  this.play()  
},  
methods: {  
  play() {  
    this.sourceUrl = 'http://10.184.49.8:9000/ipublish.bucket/5E25BEFB-BA8B-4007-8041-592453F0F5FF.avi'  
    setTimeout(() => {  
      this.sourceUrl = ''  
      this.$nextTick(() => {  
        this.play()  
      })  
    }, 10000)  
  }  
}

预期结果

预期能正常回收内存并维持在稳定水平,不会一直增长。

实际结果

内存占用规律性增长,直至闪退。

bug描述

项目场景是在屏幕上按照服务端提供的坐标渲染图片、文字、视频,所以整个项目就一个page,通过socket接收发布消息后下载文件,然后渲染到屏幕上,关键在于播放中会有刷新,比如播放一些内容60秒后,再播放另一些内容60秒,一直轮流播放。

切换的时候我通过v-if来更新vue的data,子组件(video、image)也都触发了beforeDestroy等钩子函数,但发现内存一直在增长。

为了验证,我重新创建一个空的新应用(testuni.zip),页面打开后设置子组件(里面只有一个video)显示并播放,倒计时十秒后v-if清空子组件,然后又重新为v-if设置新的值,使得子组件重新创建并播放,使用android Profiler监测内存占用记录,截图如下:

video刷新测试内存检测

一会儿之后就闪退了,如截图所示:

闪退截图

设备那边给的限制是内存占用超过300MB,或者CPU占用超过30%,就杀掉进程,此处应该是内存超过300MB被杀掉了。

因为要做自动播放,所以不能用webview嵌入h5的方式来代替,生产环境BUG,万分焦急,还请官方大大帮忙看下,感谢。

开发环境信息

信息
产品分类 uniapp/App
PC开发环境操作系统 Windows
PC开发环境操作系统版本号 win10专业版1903
HBuilderX类型 正式
HBuilderX版本号 3.5.3
手机系统 Android
手机系统版本号 Android 6.0
手机厂商 hikvision
手机机型 DS-KH9310
页面类型 vue
vue版本 vue2
打包方式 离线
项目创建方式 HBuilderX

logcat日志关键处

02-09 11:16:45.921 380-397/system_process I/art: Background partial concurrent mark sweep GC freed 17526(1664KB) AllocSpace objects, 21(336KB) LOS objects, 19% free, 8MB/10MB, paused 4.401ms total 132.733ms
...
02-09 11:17:19.122 380-445/system_process D/ActivityManagerService: moveHomeStackTaskToTop: moving TaskRecord{698988b #103 A=com.hik.vis.indoor U=0 sz=1}
...
02-09 11:17:19.542 380-12020/system_process W/art: Long monitor contention event with owner method=void com.android.server.am.ActivityManagerService$MainHandler.handleMessage(android.os.Message) from ActivityManagerService.java:1430 waiters=3 for 305ms

8 回复

试一下使用v-show 并停止视频播放。 然后广告结束后,更换视频链接。这样饶过去。
可能是v-if 多次渲染,并且内存未释放,所以不断增加。
或者在v-if隐藏时,销毁video


感谢,之前尝试过,也没用,我就算只放一个video,不执行其他任何操作,都会退出,因为我这边的设备不像手机这么好,性能很差的

大佬这个问题解决了吗,遇到了类似的场景和情况

没有解决,换方案了,业务不是很复杂,换了原生开发

我也遇到类似问题了,大佬们解决了吗?

所以你最后解决了吗?

这个问题解决了吗大佬。

在处理 uni-app 中 <video> 组件重新渲染导致的内存泄漏和闪退问题时,通常是由于视频组件没有正确释放资源或重复创建视频实例导致的。以下是一些代码示例和最佳实践,可以帮助你管理和优化 <video> 组件的内存使用。

1. 使用 v-if 控制视频组件的挂载与卸载

通过 v-if 指令动态控制 <video> 组件的渲染,确保在不需要时完全卸载组件,从而释放相关资源。

<template>
  <view>
    <button @click="toggleVideo">Toggle Video</button>
    <video
      v-if="showVideo"
      id="myVideo"
      src="https://example.com/video.mp4"
      @ended="onVideoEnd"
    ></video>
  </view>
</template>

<script>
export default {
  data() {
    return {
      showVideo: false,
    };
  },
  methods: {
    toggleVideo() {
      this.showVideo = !this.showVideo;
    },
    onVideoEnd() {
      // Optionally, you can reset showVideo to false here to unload the video after playback
      // this.showVideo = false;
    },
  },
  beforeDestroy() {
    // Optionally, you can manually clean up the video element if needed
    const videoElem = this.$el.querySelector('#myVideo');
    if (videoElem) {
      videoElem.pause();
      videoElem.src = ''; // Clear source to release the video resource
    }
  },
};
</script>

2. 手动管理视频资源

在某些情况下,你可能需要手动管理视频资源的加载和释放。这可以通过在组件销毁前暂停视频并清空其 src 属性来实现,如上面的 beforeDestroy 钩子所示。

3. 使用 ref 引用视频元素

如果你需要在 JavaScript 中直接操作视频元素,可以使用 ref 引用。

<template>
  <view>
    <video ref="videoElem" src="https://example.com/video.mp4"></video>
    <button @click="pauseVideo">Pause Video</button>
  </view>
</template>

<script>
export default {
  methods: {
    pauseVideo() {
      this.$refs.videoElem.pause();
    },
  },
  beforeDestroy() {
    const videoElem = this.$refs.videoElem;
    if (videoElem) {
      videoElem.pause();
      videoElem.src = ''; // Release resource
    }
  },
};
</script>

总结

通过合理使用 v-if 控制组件的挂载与卸载,以及在组件销毁前手动管理视频资源,可以有效避免 uni-app 中 <video> 组件重新渲染导致的内存泄漏问题。这些实践有助于确保应用在 Android 设备上的稳定性和性能。

回到顶部