您现在的位置是:百科 >>正文

androidhandler内存泄漏

百科33242人已围观

简介写Android代码,Handler这关谁都绕不过去。但用不好它,内存泄漏就是分分钟的事。我见过一个项目,退出Activity后内存死活降不下来,用MAT一查,好家伙,一个Handler死死拽着Act ...

写Android代码,内存Handler这关谁都绕不过去。泄漏但用不好它,内存内存泄漏就是泄漏分分钟的事。我见过一个项目,内存退出Activity后内存死活降不下来,泄漏用MAT一查,内存好家伙,泄漏一个Handler死死拽着Activity不放。内存

问题出在哪儿?泄漏Handler、Looper、内存MessageQueue这三兄弟是泄漏绑在一起的。主线程的内存Looper生命周期跟应用一样长,你new一个Handler,泄漏它默认就绑在主线程的内存Looper上。当你往MessageQueue里扔一个延迟消息,这个Message就会持有Handler的引用,Handler如果是非静态内部类,又隐式持有外部类(通常是Activity)的引用。链条就成了:MessageQueue -> Message -> Handler -> Activity。只要消息没执行完,Activity就别想被回收。

最典型的场景:在Activity里写个handler.postDelayed(runnable, 60000),用户打开这个页面两秒就退出了。那个Runnable还躺在消息队列里等一分钟。这一分钟里,Activity实例一直活着。如果这个Activity占了几十兆的Bitmap,内存压力直接拉满。

有人会说,那我用handler.removeCallbacksAndMessages(null)不就行了?对,这是必须做的。在onDestroy()里清掉所有消息和回调。但很多人忘了,或者压根不知道。更隐蔽的是,有些第三方库内部用了Handler,你没法控制它什么时候清理。我就遇到过某个图片加载库,内部Handler持有Context导致泄漏,最后只能换成弱引用方案。

弱引用怎么搞?把Handler改成静态内部类,然后对Activity持弱引用。这样即使消息没执行,GC也能把Activity收走。代码大概长这样:

private static class SafeHandler extends Handler {  private final WeakReference<MainActivity> mActivityRef; SafeHandler(MainActivity activity) {  mActivityRef = new WeakReference<>(activity); } @Override public void handleMessage(Message msg) {  MainActivity activity = mActivityRef.get(); if (activity == null || activity.isFinishing()) {  return; } // 正常处理消息 } } 

静态内部类不持有外部类引用,弱引用又不会阻止GC。双保险。但注意,弱引用可能在消息执行前就被清了,所以get()之后必须判空。有人图省事直接用activity.isFinishing(),结果activity已经是null了,直接NPE崩溃。

还有个坑:HandlerThread。用完之后不调用quitSafely()或者quit(),线程一直活着,里面的Looper和MessageQueue也一直活着。如果这个HandlerThread里又持有了一些Context,照样泄漏。我见过一个日志模块,每次初始化都new一个HandlerThread,从来不退出。跑一天下来,几十个线程在那挂着,内存不炸才怪。

说到底,Handler内存泄漏的本质就一句话:长生命周期的对象持有了短生命周期对象的引用。MessageQueue是长命的,Activity是短命的,中间靠Handler和Message搭了桥。把桥拆了——要么清消息,要么断引用——问题就解决了。

实际开发中,我建议直接上Lifecycle或者ViewModel配合LiveData,从根上避开手动管理Handler的麻烦。但如果维护老代码,或者必须用Handler,那就老老实实:静态内部类 + 弱引用 + onDestroy清理。三件套少一件都可能翻车。

最后提一嘴,LeakCanary装上,别等OOM了才去查。那玩意儿一报警,基本就是实锤。我现在的项目里,LeakCanary一响,不管多忙都得先把它灭了。内存泄漏这种事,攒着攒着就成雪崩了。

Tags:

上一篇:必看书籍

下一篇:福建防渗膜销售

相关文章

  • jsp实现购物车思路

    百科

    购物车这玩意儿,说穿了就是个临时存东西的地儿。用户在页面上点“加入购物车”,后端得把商品ID、数量、单价这些信息记下来。JSP里最常用的办法就是塞进Session——毕竟Session天生就是跟着用户 ...

    【百科】

    阅读更多
  • 浏览器考试网页可以监控到电脑是否被远程

    百科

    打开考试页面之前,你最好先确认一件事:电脑上有没有开着TeamViewer、向日葵、AnyDesk,或者干脆是Windows自带的远程桌面。因为现在很多在线考试系统的监考模块,已经不只是调用摄像头和麦 ...

    【百科】

    阅读更多
  • zabbix邮件报警

    百科

    Zabbix 监控再好,报警发不出去等于白装。我见过太多人把服务器、交换机、数据库全接进 Zabbix,仪表盘花花绿绿挺好看,结果磁盘爆了没人知道——因为邮件报警没配通。这事儿的核心就一句话:Zabb ...

    【百科】

    阅读更多


友情链接