HarmonyOS7 内存管理:避免泄漏的 8 条军规

📅 2026/7/16 20:59:01
HarmonyOS7 内存管理:避免泄漏的 8 条军规
文章目录前言军规 1页面销毁时关闭长连接代码实现军规 2移除全局事件监听核心代码军规 3定时器用完清掉完整示例军规 4大图及时释放代码解析军规 5避免意外的全局引用实现拆解军规 6State 别挂巨大对象军规 7循环引用要断军规 8用 Profiler 实测别靠感觉代码清单常见误区小白必踩完整可运行示例避免闭包引用泄漏关键代码写在最后前言app 用着用着越来越卡、最后闪退——八成是内存泄漏。对象用完了本该释放却因为某些引用挂着迟迟不释放越积越多系统只好杀掉你。内存管理没有银弹但有军规。我把 HarmonyOS 里最容易漏的 8 个点列成清单每条都告诉你为什么会漏、怎么改。照着排查泄漏能少一大半。军规 1页面销毁时关闭长连接WebSocket、长轮询在页面退出后还连着引用着页面对象导致整个页面无法回收。代码实现aboutToAppear(){this.wswebSocket.createWebSocket()this.ws.connect(URL)}aboutToDisappear(){this.ws?.close()// ✅ 退出必须关this.wsundefined}凡是aboutToAppear里开的资源连接、监听、定时器必须在aboutToDisappear里释放。这是铁律。军规 2移除全局事件监听在AppStorage、全局单例上注册了监听页面销毁没注销页面就被监听器拽住死不了。核心代码aboutToAppear(){this.listener(v){/* ... */}AppStorage.on(theme,this.listener)}aboutToDisappear(){AppStorage.off(theme,this.listener)// ✅ 注销}军规 3定时器用完清掉setInterval不清除会一直跑且持有回调里的页面引用。完整示例this.timersetInterval(()this.tick(),1000)// 退出时clearInterval(this.timer)军规 4大图及时释放列表里加载的原图、Canvas 的大位图占用巨大。用缩略图、离开页面时清空引用。代码解析// 列表用缩略图别用原图Image(item.thumb).width(80).height(80)// 大图预览关闭后把 url 置空让 GC 回收this.bigImageUrl军规 5避免意外的全局引用把页面对象塞进全局数组、单例忘了清页面永远不释放。实现拆解// 危险把整个页面存进全局GlobalCache.pages.push(this)// 正确只存需要的轻量数据用完删GlobalCache.ids.push(this.id)军规 6State 别挂巨大对象状态装饰器会让框架持续观察对象。把一个超大数组挂State每次变更都深度比对既耗内存又耗 CPU。大数据用普通变量 手动刷新或分页。军规 7循环引用要断A 引用 BB 又引用 AGC 无法回收。组件间用事件/回调解耦避免互相持有。军规 8用 Profiler 实测别靠感觉DevEco 的 Profiler 能看内存曲线。反复进出一个页面如果内存只涨不跌必漏。代码清单操作进页面 → 退页面 → 进页面 → 退页面 正常内存曲线回到原点 泄漏每次退出都高出一截常见误区小白必踩误区说明页面销毁不关长连接WebSocket、长轮询退出后还连着拽着页面不释放 → 泄漏。不注销全局监听在 AppStorage 上注册监听页面销毁没注销页面被拽住死不了。定时器不清除setInterval不clearInterval一直跑还持有着页面引用。大图不释放列表原图、Canvas 大位图占用巨大离开页面置空让 GC 回收。下面这段代码可以直接复制到 DevEco Studio 里运行。建议你边读边敲改一改文末「动手改一改」里的参数亲眼看看效果。完整可运行示例避免闭包引用泄漏错误的定时器会持有组件正确做法在销毁时清理。关键代码// 定时器必须在 aboutToDisappear 释放EntryComponentstruct TimerPage{privatetimer?:numberStatetick:number0aboutToAppear(){this.timersetInterval((){this.tick},1000)}aboutToDisappear(){if(this.timer!undefined){clearInterval(this.timer)// 关键离开页面清掉this.timerundefined}}build(){Column(){Text(计时this.tick).fontSize(24)}.padding(20)}}你会看到什么进入页面数字每秒 1退出页面后计数停止且组件能被 GC 回收。若漏掉clearInterval页面关了定时器还在跑组件永远不释放——这就是典型泄漏。动手改一改故意删掉aboutToDisappear反复进出页面用 Profiler 看内存只增不减。把setInterval换成worker长时间任务体会不同泄漏场景。用taskpool替代定时器做周期任务减少引用负担。写在最后内存管理的核心就一句“谁开的谁关”。连接、监听、定时器在aboutToDisappear里一一对应地释放。这 8 条里前 3 条关连接、注销监听、清定时器覆盖了 80% 的泄漏。建议你现在就用 Profiler 抓一次进/出页面的内存曲线看看有没有只涨不跌——有的话按这 8 条逐条查问题大概率就在其中。