浅析Handler引起的内存泄漏及解决方法
来源:互联网 发布:亲情关怀是什么软件 编辑:程序博客网 时间:2024/05/16 09:55
在进行异步操作时,我们经常会使用到Handler类。最常见的写法如下。
但是,这段代码有可能会引起内存泄漏。我们来分析一下内存泄漏是如何发生的。
当使用内部类或匿名内部类的方式创建Handler时,Handler对象会隐式地持有一个外部类对象的引用(这里的外部类是Activity)。一般在一个耗时任务中会开启一个子线程,如网络请求或文件读写操作,我们会使用到Handler对象。但是,如果在任务未执行完时,Activity被关闭了,Activity已不再使用,此时由GC来回收掉Activity对象。由于子线程未执行完毕,子线程持有Handler的引用,而Handler又持有Activity的引用,这样直接导致Activity对象无法被GC回收,即出现内存泄漏。
下面用一段代码示例来说明。
在MainActivity启动时,开启一个子线程来下载文件。如果文件较大或网络不稳定的因素,导致短时间内无法执行完成,用户按下返回键退出了当前界面。此时子线程仍然在运行,并持有mHandler的引用,而mHandler是一个匿名内部类的对象,持有MainActivity的引用,这样MainActivity对象无法被回收,MainActivity内部的很多资源都无法被回收。
对于这个问题,来自Android Framework的工程师Romain Guy在google groups上给出了解释和建议。
链接:
https://groups.google.com/forum/?fromgroups=#%21msg/android-developers/1aPZXZG6kWk/lIYDavGYn5UJ
截图:
另外,在androiddesignpatterns上也有人给出了解决方案:
http://www.androiddesignpatterns.com/2013/01/inner-class-handler-memory-leak.html
解决方法主要在于两点:
1.将Handler声明为静态内部类。因为静态内部类不会持有外部类的引用,所以不会导致外部类实例出现内存泄露。
2.在Handler中添加对外部Activity的弱引用。由于Handler被声明为静态内部类,不再持有外部类对象的引用,导致无法在handleMessage()中操作Activity中的对象,所以需要在Handler中增加一个对Activity的弱引用。
改善之后的代码如下。
关于WeakReference的说明:
WeakReference即弱引用,与强引用(即我们常说的“引用”)相对。它的特点是,GC在回收时会忽略掉弱引用,即就算有弱引用指向某对象,但只要该对象没有被强引用指向,该对象就会在被GC检查到时回收掉。
但是,这段代码有可能会引起内存泄漏。我们来分析一下内存泄漏是如何发生的。
当使用内部类或匿名内部类的方式创建Handler时,Handler对象会隐式地持有一个外部类对象的引用(这里的外部类是Activity)。一般在一个耗时任务中会开启一个子线程,如网络请求或文件读写操作,我们会使用到Handler对象。但是,如果在任务未执行完时,Activity被关闭了,Activity已不再使用,此时由GC来回收掉Activity对象。由于子线程未执行完毕,子线程持有Handler的引用,而Handler又持有Activity的引用,这样直接导致Activity对象无法被GC回收,即出现内存泄漏。
下面用一段代码示例来说明。
在MainActivity启动时,开启一个子线程来下载文件。如果文件较大或网络不稳定的因素,导致短时间内无法执行完成,用户按下返回键退出了当前界面。此时子线程仍然在运行,并持有mHandler的引用,而mHandler是一个匿名内部类的对象,持有MainActivity的引用,这样MainActivity对象无法被回收,MainActivity内部的很多资源都无法被回收。
对于这个问题,来自Android Framework的工程师Romain Guy在google groups上给出了解释和建议。
链接:
https://groups.google.com/forum/?fromgroups=#%21msg/android-developers/1aPZXZG6kWk/lIYDavGYn5UJ
截图:
另外,在androiddesignpatterns上也有人给出了解决方案:
http://www.androiddesignpatterns.com/2013/01/inner-class-handler-memory-leak.html
解决方法主要在于两点:
1.将Handler声明为静态内部类。因为静态内部类不会持有外部类的引用,所以不会导致外部类实例出现内存泄露。
2.在Handler中添加对外部Activity的弱引用。由于Handler被声明为静态内部类,不再持有外部类对象的引用,导致无法在handleMessage()中操作Activity中的对象,所以需要在Handler中增加一个对Activity的弱引用。
改善之后的代码如下。
关于WeakReference的说明:
WeakReference即弱引用,与强引用(即我们常说的“引用”)相对。它的特点是,GC在回收时会忽略掉弱引用,即就算有弱引用指向某对象,但只要该对象没有被强引用指向,该对象就会在被GC检查到时回收掉。
对于上面在子线程中下载文件的示例代码,改为采用WeakReference之后,如果任务未执行完但是用户却关闭了MainActivity,但由于仅有一个来自MyHandler的弱引用指向MainActivity,所以GC仍然会在检查时把MainActivity回收掉。这样,内存泄露的问题就不会出现了。
原博主链接:http://blog.csdn.net/ruancoder/article/details/52448642
阅读全文
0 0
- 浅析Handler引起的内存泄漏及解决方法
- 浅析Handler引起的内存泄漏及解决方法
- 浅析Handler引起的内存泄漏及解决方法
- Android handler 引起的内存泄漏
- 解决由Handler 引起的内存泄漏
- 安卓-Handler引起的内存泄漏
- Handler引起的内存泄漏解决办法
- 内存泄漏检测工具和Handler引起的内存泄漏问题
- android Handler引起内存泄漏
- Android开发常见问题之Handler引起的内存泄漏
- Android开发-Handler引起的内存泄漏-实验、分析、总结。
- Handler 非静态内部引起的内存泄漏问题
- Handler使用引起的内存泄漏原因以及解决办法
- Android开发-Handler引起的内存泄漏-实验、分析、总结。
- Handler引起的内存泄露及解决办法
- android学习——Handler引起的内存泄露及解决方法
- Handler使用引起内存泄漏分析
- Android Handler内存泄漏解决方法
- scrapy-redis环境配置
- gcc 编译信息输出到文本文件
- matlab基本数组和向量操作
- 第三章 扩展你的博客应用
- 关于springMVC文件上传过程中一个有意思的小细节
- 浅析Handler引起的内存泄漏及解决方法
- StatusBar
- 二分法查找示例
- 微信小程序登录(基于java后台)
- LeetCode-96. Unique Binary Search Trees
- tableView滚动到指定行
- sparkSQL读取hive分区表的问题追踪
- css选择器与权重
- Angular开发(二十二)-angular处理复选框选值的问题