uni-app重新渲染video时内存一直上涨直至闪退 android app-vue
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监测内存占用记录,截图如下:
一会儿之后就闪退了,如截图所示:
设备那边给的限制是内存占用超过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
试一下使用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 设备上的稳定性和性能。