android 下 computed变量在页面销毁时没有进行回收导致内存泄露的uni-app问题
android 下 computed变量在页面销毁时没有进行回收导致内存泄露的uni-app问题
| 开发环境 | 版本号 | 项目创建方式 |
|---|---|---|
| Mac | 15.6.1 (24G90) | HBuilderX |
产品分类:uni-app x/App
PC开发环境操作系统:Mac
HBuilderX类型:Alpha
HBuilderX版本号:4.81
手机系统:Android
手机系统版本号:Android 16
手机厂商:模拟器
手机机型:36.1.9-13823996
页面类型:nvue
vue版本:vue3
打包方式:离线
项目创建方式:HBuilderX
操作步骤:
- 使用
computed,通过redirectTo销毁页面
预期结果:
- 应该在销毁前进行
computed的垃圾回收,避免出现内存泄露
实际结果:
┬───
│ GC Root: Thread object
│
├─ android.os.HandlerThread instance
│ Leaking: NO (PathClassLoader↓ is not leaking)
│ Thread name: 'LeakCanary-Heap-Dump'
│ ↓ Thread.contextClassLoader
├─ dalvik.system.PathClassLoader instance
│ Leaking: NO (InternalLeakCanary↓ is not leaking and A ClassLoader is never leaking)
│ ↓ ClassLoader.runtimeInternalObjects
├─ java.lang.Object[] array
│ Leaking: NO (InternalLeakCanary↓ is not leaking)
│ ↓ Object[554]
├─ leakcanary.internal.InternalLeakCanary class
│ Leaking: NO (UniPortraitPageActivity↓ is not leaking and a class is never leaking)
│ ↓ static InternalLeakCanary.resumedActivity
├─ io.dcloud.uniapp.appframe.activity.UniPortraitPageActivity instance
│ Leaking: NO (Activity#mDestroyed is false)
│ mApplication instance of io.dcloud.uniapp.UniApplication
│ mBase instance of androidx.appcompat.view.ContextThemeWrapper
│ ↓ UniPageActivity.page
│ ~~~~
├─ io.dcloud.uniapp.appframe.a instance
│ Leaking: UNKNOWN
│ Retaining 3.9 kB in 114 objects
│ C instance of io.dcloud.uniapp.appframe.activity.UniPortraitPageActivity with mDestroyed = false
│ ↓ a.p
│ ~
├─ io.dcloud.uniapp.dom.UniNativeDocumentImpl instance
│ Leaking: UNKNOWN
│ Retaining 22.7 MB in 503465 objects
│ ↓ UniNativeDocumentImpl.calculatedCallback
│ ~~~~~~~~~~~~~~~~~~
├─ io.dcloud.uniapp.framework.IndexKt$$ExternalSyntheticLambda48 instance
│ Leaking: UNKNOWN
│ Retaining 22.5 MB in 499985 objects
│ ↓ IndexKt$$ExternalSyntheticLambda48.f$0
│ ~~~
├─ io.dcloud.uniapp.framework.extapi.IndexKt$$ExternalSyntheticLambda33 instance
│ Leaking: UNKNOWN
│ Retaining 22.5 MB in 499984 objects
│ ↓ IndexKt$$ExternalSyntheticLambda33.f$0
│ ~~~
├─ uni.UNI0B065E9.GenPagesCbtMoodChoose instance
│ Leaking: UNKNOWN
│ Retaining 22.5 MB in 499983 objects
│ ↓ Page.$nativePage
│ ~~~~~~~~~~~
├─ io.dcloud.uniapp.appframe.a instance
│ Leaking: UNKNOWN
│ Retaining 929 B in 27 objects
│ ↓ a.O
│ ~
├─ io.dcloud.uniapp.appframe.ui.PageFrameView instance
│ Leaking: YES (View.mContext references a destroyed activity)
│ Retaining 16.6 kB in 181 objects
│ View not part of a window view hierarchy
│ View.mAttachInfo is null (view detached)
│ View.mID = R.id.null
│ View.mWindowAttachCount = 1
│ mContext instance of io.dcloud.uniapp.appframe.activity.UniPortraitPageActivity with mDestroyed = true
│ ↓ View.mContext
╰→ io.dcloud.uniapp.appframe.activity.UniPortraitPageActivity instance
Leaking: YES (ObjectWatcher was watching this because io.dcloud.uniapp.appframe.activity.UniPortraitPageActivity received Activity#onDestroy() callback and Activity#mDestroyed is true)
Retaining 76.6 kB in 1370 objects
key = 33c56a99-5d1c-47f3-925f-83289c3e16e8
watchDurationMillis = 6857
retainedDurationMillis = 1855
mApplication instance of io.dcloud.uniapp.UniApplication
mBase instance of androidx.appcompat.view.ContextThemeWrapper
更多关于android 下 computed变量在页面销毁时没有进行回收导致内存泄露的uni-app问题的实战教程也可以访问 https://www.itying.com/category-93-b0.html
我也遇到类似问题,参考这篇教程也没有修复:https://doc.dcloud.net.cn/uni-app-x/tutorial/android-memoryleak.html#android平台内存泄漏排查教程
更多关于android 下 computed变量在页面销毁时没有进行回收导致内存泄露的uni-app问题的实战教程也可以访问 https://www.itying.com/category-93-b0.html
这是一个典型的 uni-app 页面销毁时 computed 变量未正确释放导致的内存泄漏问题。
从泄漏堆栈分析可以看出:
- 泄漏根源是
UniNativeDocumentImpl.calculatedCallback持有对页面的引用 - 页面通过
redirectTo导航后,虽然 Activity 已销毁(mDestroyed = true),但 computed 相关的回调函数仍然保持对页面上下文的强引用 - 导致 22.5 MB 内存无法被垃圾回收
解决方案:
- 在页面 onUnload 生命周期中手动清理 computed 依赖
onUnload() {
// 手动清理 computed 相关的响应式依赖
this.$scope.$destroy()
}
-
检查 computed 函数中是否存在闭包引用 确保 computed 函数没有引用外部变量或 DOM 元素,特别是避免在 computed 中直接操作页面元素。
-
使用 weakRef 优化 对于可能引起循环引用的场景,考虑使用 WeakRef 来持有页面引用。
-
临时规避方案 在调用
redirectTo前,可以尝试先重置页面的 computed 数据:
// 跳转前清理
this.someComputedData = null
uni.redirectTo({ url: '/pages/target' })

