handler引起内存泄露

Android Handler leak分析及解决办法详解 主要介绍了Android Handler leak分析及解决办法详解的相关资料,需要的朋友可以参考下 立即下载


摘要 内存泄露,听起来很屌的样子?看了这篇文章,你会发现其实这个概念很简单。Android程序经常出现的一个现象是:内存占用越来越大,到最后用户不得不强行关闭程序来释放内存。导致内存越来越大的原因很多,其中最主要的原因之一,就是Handler使用不当导致的内存泄露。
Android Handler 内存泄露 Memory Leak


什么是内存泄露?
Java使用有向图机制,通过GC自动检查内存中的对象(什么时候检查由虚拟机决定),如果GC发现一个或一组对象为不可到达状态,则将该对象从内存中回收。也就是说,一个对象不被任何引用所指向,则该对象会在被GC发现的时候被回收;另外,如果一组对象中只包含互相的引用,而没有来自它们外部的引用(例如有两个对象A和B互相持有引用,但没有任何外部对象持有指向A或B的引用),这仍然属于不可到达,同样会被GC回收。


Android中使用Handler造成内存泄露的原因


?
1
2
3
4
5
6
Handler mHandler = new Handler() {
    @Override
    public void handleMessage(Message msg) {
        mImageView.setImageBitmap(mBitmap);
    }
}
上面是一段简单的Handler的使用。当使用内部类(包括匿名类)来创建Handler的时候,Handler对象会隐式地持有一个外部类对象(通常是一个Activity)的引用(不然你怎么可能通过Handler来操作Activity中的View?)。而Handler通常会伴随着一个耗时的后台线程(例如从网络拉取图片)一起出现,这个后台线程在任务执行完毕(例如图片下载完毕)之后,通过消息机制通知Handler,然后Handler把图片更新到界面。然而,如果用户在网络请求过程中关闭了Activity,正常情况下,Activity不再被使用,它就有可能在GC检查时被回收掉,但由于这时线程尚未执行完,而该线程持有Handler的引用(不然它怎么发消息给Handler?),这个Handler又持有Activity的引用,就导致该Activity无法被回收(即内存泄露),直到网络请求结束(例如图片下载完毕)。另外,如果你执行了Handler的postDelayed()方法,该方法会将你的Handler装入一个Message,并把这条Message推到MessageQueue中,那么在你设定的delay到达之前,会有一条MessageQueue -> Message -> Handler -> Activity的链,导致你的Activity被持有引用而无法被回收。


内存泄露的危害
只有一个,那就是虚拟机占用内存过高,导致OOM(内存溢出),程序出错。对于Android应用来说,就是你的用户打开一个Activity,使用完之后关闭它,内存泄露;又打开,又关闭,又泄露;几次之后,程序占用内存超过系统限制,FC。


使用Handler导致内存泄露的解决方法
方法一:通过程序逻辑来进行保护。
1.在关闭Activity的时候停掉你的后台线程。线程停掉了,就相当于切断了Handler和外部连接的线,Activity自然会在合适的时候被回收。 
2.如果你的Handler是被delay的Message持有了引用,那么使用相应的Handler的removeCallbacks()方法,把消息对象从消息队列移除就行了。 
方法二:将Handler声明为静态类。
静态类不持有外部类的对象,所以你的Activity可以随意被回收。代码如下:


?
1
2
3
4
5
6
static class MyHandler extends Handler {
    @Override
    public void handleMessage(Message msg) {
        mImageView.setImageBitmap(mBitmap);
    }
}
但其实没这么简单。使用了以上代码之后,你会发现,由于Handler不再持有外部类对象的引用,导致程序不允许你在Handler中操作Activity中的对象了。所以你需要在Handler中增加一个对Activity的弱引用(WeakReference):




?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
static class MyHandler extends Handler {
    WeakReference<Activity > mActivityReference;
 
    MyHandler(Activity activity) {
        mActivityReference= new WeakReference<Activity>(activity);
    }
 
    @Override
    public void handleMessage(Message msg) {
        final Activity activity = mActivityReference.get();
        if (activity != null) {
            mImageView.setImageBitmap(mBitmap);
        }
    }
}
将代码改为以上形式之后,就算完成了。


延伸:什么是WeakReference?
WeakReference弱引用,与强引用(即我们常说的引用)相对,它的特点是,GC在回收时会忽略掉弱引用,即就算有弱引用指向某对象,但只要该对象没有被强引用指向(实际上多数时候还要求没有软引用,但此处软引用的概念可以忽略),该对象就会在被GC检查到时回收掉。对于上面的代码,用户在关闭Activity之后,就算后台线程还没结束,但由于仅有一条来自Handler的弱引用指向Activity,所以GC仍然会在检查的时候把Activity回收掉。这样,内存泄露的问题就不会出现了。
智能问数产品背后的Agent技术揭秘:从任务分解到工具调用的完整流程 本文深入解析智能问数产品背后的Agent技术,从任务分解到工具调用的完整流程。通过大模型驱动的语义理解和动态工具调度,Agent系统能高效处理复杂数据分析需求,显著提升响应速度和准确率。文章详细介绍了模块化架构、任务分解机制、动态工具调用及双通道记忆系统等核心技术,展示了大模型时代的新型数据分析范式。 阅读详情

相关推荐

mysql笔记:23. 在Mac上安装与卸载MySQL

MySQL对Mac电脑的适配十分强大,再加上Mac本身就是Unix操作系统演化而来的,所以在Mac上安装MySQL的方式有多种。常见的方法有如下三种:DMG、brew、TAR。介绍这些方法前,我们先了解下MySQL安装文件的下载。

斌斌(Java) 2247

Android中使用Handler造成内存泄露的分析和解决

2019独角兽企业重金招聘Python工程师标准>>> ...

weixin_34342905的博客 496

Android开发者必看:5分钟搞定MQTT客户端连接EMQX服务器(附完整代码)

本文为Android开发者提供了一份快速实现MQTT客户端连接EMQX服务器的实战指南。通过引入Eclipse Paho SDK,详细讲解了从项目配置、权限申请到核心连接、主题订阅与消息发布的完整流程,并附有即拿即用的Kotlin代码,帮助开发者在物联网应用中高效集成轻量级实时通信功能。

weixin_29228781的博客 270

android内存泄漏---常见内存泄露的问题

1,编写单例的时候常出现的错误。      错误方式:      public class Foo{           private static Foo foo;           private Context mContext;           private Foo(Context mContext){                this.mContext = m

Steampy专栏 670

SAR成像系列:【3】合成孔径雷达(SAR)的二维回波信号与简单距离多普勒(RD)算法 (附matlab代码)

二维回波信号分析

zr2006_7的专栏 2万+

WeakReference的使用和在Android中的应用

先介绍下WeakReferenceWeakReference在java中被称为弱引用,其父类为Reference,其兄弟还有强引用,软应用,虚引用.一般强引用指向的对象java虚拟机是 不会主动回收的(除非java虚拟机判断该引用对象不再使用了,例如在某个方法中的局部变量,引用会从方法栈出弹出),而弱引用不一样,其回 收时机是下一次java发生gc动作时(此时没有其他的强引用指向它,并且该强应用

aa671125的专栏 964

基于陀螺仪航向反馈的轮式机器人PID直线控制

航向角控制是移动机器人实现稳定直线运动的基础技术,其本质是通过实时感知机体朝向偏差并动态调节驱动输出,以抵消机械不对称、轮径误差等固有扰动。该方法依托陀螺仪测量角速度并积分解算航向角,结合离散化PID算法生成补偿性PWM指令,在嵌入式平台(如STM32)上构建低延迟闭环。相比依赖编码器的速度闭环,它规避了轮径标定与安装偏心等误差源,显著提升低成本平台的工程鲁棒性与部署效率。典型应用场景包括教育机器人直线循迹、AGV基础导航模块开发及IMU-PID融合控制原型验证。

web39explorer的博客 1108

Android中的WeakReference弱引用的正确理解

如果一个对象只具有弱引用(就是说弱引用指向了某个对象,但只要该对象不是强引用或没有被强引用指向),那么在垃圾回收器线程扫描的过程中,一旦发现了只具有弱引用的对象,不管当前内存空间足够与否,都会回收它的内存。不过,由于垃圾回收器是一个优先级很低的线程,因此不一定会很快发现那些只具有弱引用的对象。弱引用也可以和一个引用队列(ReferenceQueue)联合使用,如果弱引用所引用的对象被垃圾回收,Java虚拟机就会把这个弱引用加入到与之关联的引用队列中。在Activity中使用WeakReference...

UrasakiNakajima的博客 4108

瑞萨MCU定时器API实战:从Smart Configurator配置到中断与输入捕获应用

在嵌入式系统开发中,定时器(Timer)是实现精准时序控制、PWM输出和信号测量的核心硬件外设。其工作原理基于计数器在稳定时钟源驱动下递增或递减,达到预设值后触发中断或改变输出电平,从而为系统提供节拍和事件基准。通过图形化配置工具(如瑞萨的Smart Configurator),开发者可以高效地将复杂的硬件寄存器操作转化为清晰、标准化的C语言API函数,这极大地提升了开发效率并降低了出错风险。这种从硬件抽象到软件接口的技术价值在于,它使得开发者能更专注于应用逻辑,而非底层细节,尤其适用于工业控制、汽车电子等

weixin_42519733的博客 274

R 语言 ggplot2 绘制精美高级全球地图

在本教程中,我们将学习如何使用R语言和ggplot2包绘制精美高级地图。ggplot2是一个功能强大的数据可视化包,它可以让我们创建漂亮、交互式的地图。我们将使用R中的一些其他包来处理地理空间数据,以便与ggplot2无缝协作。

Mrrunsen的博客 1866

Android ---【内存优化】Handler 内存泄漏原因及解决方案

Handler造成内存泄露的原因。非静态内部类,或者匿名内部类。使得Handler默认持有外部类的引用。在Activity销毁时,由于Handler可能有未执行完/正在执行的Message。导致Handler持有Activity的引用。进而导致GC无法回收Activity。匿名内部类: 非静态内部类: 三、解决方法 静态内部类+弱引用 Activity销毁时,清空Handler中,未执行或正在执行的Callback以及Message。 四、内部类为什么会持有外部类的引用 这是因为内部类虽然和外部类写在同一个

梁同学与Android 8275

游戏大厂状态同步与帧同步技术全解析——让虚拟世界万物协同的“时间齿轮”

本文深入解析了大厂游戏开发中的两种核心同步技术:状态同步和帧同步。状态同步适合大型MMO和FPS游戏,由服务端计算并广播世界状态;帧同步则通过统一操作输入实现MOBA和RTS游戏的绝对公平。文章详细比较了两者的差异、适用场景和底层实现原理,并揭秘了《王者荣耀》《PUBG》等热门游戏的同步机制。同时探讨了本地预测、延迟补偿、防作弊等关键技术,以及未来AI和云游戏带来的同步新挑战,为开发者提供了全面的技术参考和实践指南。

本博客聚焦游戏开发技巧、创业实战心得及大学热门课程干货。这里既有技术深度,也有思维广度,无论你是开发者、创业者还是高校学子,都能在这里找到适合自己的成长之路! 916

Android App 内存泄露之Handler

Android App 内存泄露之Handler, 你可能忽略的东东

The Tech-Dragon 3万+

华为的C语言编程规范.pdf

华为技术有限公司内部技术规范。本规范制定了编写C语言程序的基本原则、规则和建议。从代码的清晰、简洁、可测试、安全、程序效率、可移植各个方面对C语言编程作出了具体指导。

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

Handler中的内存泄露

预备文章: Handler与Looper GC可达性实践-内存泄露分析 场景1 看码识错误1: class Scene1Activity : AppCompatActivity() { private val mHandler = Handler() override fun onCreate(savedInstanceState: Bundle?) { supe...

wfeii的博客 1432

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

【Android】Handler造成内存泄露分析

Java使用有向图机制,通过GC自动检查内存中的对象(什么时候检查由虚拟机决定),如果GC发现一个或一组对象为不可到达状态,则将该对象从内存中回收。也就是说,一个对象不被任何引用所指向,则该对象会在被GC发现的时候被回收;另外,如果一组对象中只包含互相的引用,而没有来自它们外部的引用(例如有两个对象A和B互相持有引用,但没有任何外部对象持有指向A或B的引用),这仍然属于不可到达,同样会被GC回收。 Android中使用Handler造成内存泄露的原因 Handler mHandler = new Handl

sinat_36955332的博客 181

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

面试:Handler内存泄露的原因是什么?

前言 嗨,大家好,问大家一个“简单”的问题: Handler内存泄露的原因是什么? 你会怎么答呢? 这是错误的回答 有的朋友看到这个题表示,就这?太简单了吧。 "内部类持有了外部类的引用,也就是Hanlder持有了Activity的引用,从而导致无法被回收呗。" 其实这样回答是错误的,或者说没回答到点子上。 总结 Handler内存泄露的原因是什么? 1、原因一延迟消息 Handler导致内存泄漏一般发生在发送延迟消息的时候,当Activity关闭之后,延迟消息还没发出,那么主线程中的

王温暖的博客 3029

kotlin无内存泄露的Handler写法

不管泄露最简单写法 private val handler : Handler = object : Handler() { override fun handleMessage(msg: Message) { } } 上面这种写法编译器会警告:‘constructor Handler()’ is deprecated. Deprecated in Java 无警告写法 private val handler : Handler = object :

zmlovelx(帅得不敢出门 程序员群31843264) 2460

Android 解决handler内存泄露的方法

文章目录1、简介2、方法一避免Handler 泄露3、方法二添加弱连接 1、简介 大体理解为: Handler 在使用的时候一般要依附于一个对象,很多时候 handler 延时发送的时候 ,所依附的对象得不到释放,于是出现了 handler 泄露。 2、方法一避免Handler 泄露 1)在对象被销毁的时候 断掉与Handler 的联系,销毁Handler 消息的处理。 @Override pub...

Venus 的博客 5213

android内存泄露:handler

一、什么是内存泄露 Java使用有向图机制,通过GC自动检查内存中的对象(什么时候检查由虚拟机决定),如果GC发现一个或一组对象为不可到达状态,则将该对象从内存中回收。也就是说,一个对象不被任何引用所指向,则该对象会在被GC发现的时候被回收;另外,如果一组对象中只包含互相的引用,而没有来自它们外部的引用(例如有两个对象A和B互相持有引用,但没有任何外部对象持有指向A或B的引用),这仍然属于不可到

mybook1122的专栏 490

handler导致内存泄露的真正原因

handler是我们在更新UI时经常使用到的类,但是不注意的话,很容易就导致内存泄露,最后导致OOM,故现在探究下handler导致内存泄露的原因及有哪些常用的解决办法。 先看下面一段代码:  可以看到这段代码编辑器为我们标出了黄色,并且提示如下: This Handler class should be static or leaks might occur (anonymous ...

水煮鱼在飞的博客 1万+

Android 中 Handler 引起的内存泄露

在Android常用编程中,Handler在进行异步操作并处理返回结果时经常被使用。通常我们的代码会这样实现。 public class SampleActivity extends Activity { private final Handler mLeakyHandler = new Handler() { @Override public void handleMessage(Message...

yanglin10000的博客 318

Handler 内存泄露详细原因

1. 说Handler内存泄露这种文章挺多的,基本就是handler 使用不当 持有外部引用导致的内存泄露完毕. 2.根据可达性gc 算法,当一个引用没有被root 对象引用时,该对象内存随时被系统回收,那么handler 的引用链又是什么呢? 未指定Looper 默认就使用主Looper ,那么主Looper 在哪里创建呢?在ActivityThread类中: public static void main(String[] args) { ... ..

闪电人 332

Android Handler的内存泄露场景分析

在前面一篇博客《Android全面解析Handler》一文中,我们认识了Handler的异步通信机制,同时也提到过Handler如果使用不慎将会导致内存泄露。今天主要来讲述一下Handler的内存泄露场景可能存在的场景以及解决方案。 场景一:直接传递外部类引用到静态内部类使用,导致静态内部类间接持有外部类的引用 举个栗子,在一个静态内部类我们想访问外部类的成员属性,怎么办?可不可以直接访问了,答案当然是不想的,如下所示,我们的代码提示是会直接报错的: public class TestActivity ex

hirezy 7969

handler引起的内存泄露

什么是内存泄露? 内存泄露是指无用对象(不再使用的对象)持续占有内存或无用对象的内存得不到及时释放,从而造成的内存空间的浪费称为内存泄露。内存泄露有时不严重且不易察觉,这样开发者就不知道存在内存泄露,但有时也会很严重,会提示你Out of memory。 Java内存泄露根本原因? 长生命周期的对象持有短生命周期对象的引用就很可能发生内存泄露,尽管短生命周期对象已经不再需要,但是因为长生命周

crazy_yyyyy的专栏 540

Handler内存泄露原理及解决方法

Handler内存泄露原理及解决方法 前言 因为Android采取了单线程UI模型,开发者无法在子线程中更新UI,为此Android为我们提供了Handler这个工具,可以开发者切换到主线程更新UI。 示例 首先看一段示例代码 public class LeakCanaryActivity extends AppCompatActivity private Handler mHa

Mr_liu的博客 420
上一篇: Android之监测手机网络状态的广播
下一篇: Adapter总结
rongbinjava
博客等级 码龄11年 15粉丝 83原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值