关闭

Andorid中Handler造成的内存泄漏浅析与处理

标签: android内存泄露异步
457人阅读 评论(0) 收藏 举报

Andorid中Handler造成的内存泄漏浅析与处理

概述:

Handler机制是Android中提供的一个异步回调机制,我们可以在完成一个耗时任务后作出相应通知。

每一个消息都需要被指定的Handler处理,通过Handler创建消息便可以完成此功能。Android消息机制中 引入了消息池。Handler创建消息时首先查询消息池中是否有消息存在,如果有直接从消息池中取得,如果没有则重新初始化一个消息实例。使用消息池的好 处是:消息不被使用时,并不作为垃圾回收,而是放入消息池,可供下次Handler创建消息时使用。消息池提高了消息对象的复用,减少系统垃圾回收的次数。但是,正是这个机制,当Activity被销毁时,消息队列中有信息尚未被处理,容易引起内存泄漏。

 

正文:

下面我们举个例子:

1. 新建一个工程, 配置好leakCanary内存泄漏检测环境。(leakCanary:第三方Android和Java的内存泄露检测库)

2. 布局好UI 。(界面布局仅一个button, activity_main.xml文件中加个Button即可,Button 的ID为send_btn).

3. 在MainActivity中添加如下代码:

 

在平常项目开发中,我们经常这样使用handler类,在一个界面中加载数据loadData,加载数据完成后,发送Message,然后在在Handler的handlerMessage()中去处理我们的消息。

运行代码,我们做如下操作:

1. 点击按钮,在20秒内点击手机返回键,关闭MainActivity;

2. 等待10秒左右,会出现以下结果,此时,LeakCanary提示内存泄漏:


 

分析:

由于mhandler是Handler的匿名内部类的实例,所以它持有外部类Activity的引用,我们知道消息队列是在一个Looper线程中不断轮询处理消息,而消息队列中的Message持有mHandler实例的引用,mHandler又持有Activity的引用,那么当这个Activity退出时,消息队列中还有未处理的消息或者正在处理消息,将导致该Activity的内存资源无法及时回收,引发内存泄漏。

解决方法:

使用静态内部类,将上面的代码改一下:

 

 

修改代码后运行,重复上面相同的操作,LeakCanary并没有报出内存泄漏。但是在开发中,在我们平时使用handlerMessage处理消息时,很多时候需要去使用外部类MainActivity的函数,比如我们需要更新MainActivity的UI 。

Handler使用方式升级版: 使用弱引用 -解决静态内部类访问外部类

名词解释:弱引用-----可以被JAVA 虚拟机顺利垃圾回收的一种引用方式

代码流程如下:

1.  修改一下我们刚才例子中的UI :在MainActity的布局文件 activity_main.xml中添加一个TextView ,并且在MainActity的oncreate找到并初始化它。

代码和效果示意如下:

  

 

2. 我们在handlerMessage中,给TextView设置值,请注意红色方框内的弱引用使用方式:

 

分析上面的做法:

创建一个静态Handler内部类,然后对Handler持有的外部对象使用弱引用,这样在回收时也可以回收Handler持有的对象,解决了我们内存泄漏以及访问外部对象的问题。

但是,这样子还不够完美: 我们退出MainActivity后,Looper线程的消息队列中还是可能会有待处理的消息,啥意思呢?就是我们MainActivity退出后,消息队列里还有消息,即我们的例子中,20秒后,还收到消息队列中的消息。

更完美的做法:我们应该在Activity关闭的时候,移除消息队列中的消息。

 

 

总结:在我们以后开发中使用handler时,就可以使用静态类和弱引用,这样可以避免内存泄漏现象,达到内存优化的目的。

0
0
查看评论
发表评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场

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

关于Android中使用Handler造成内存泄露的分析和解决 什么是内存泄露? Java使用有向图机制,通过GC自动检查内存中的对象(什么时候检查由虚拟机决定),如果GC发现一个或一组对象为不可到...
  • gao_chun
  • gao_chun
  • 2015-05-27 15:03
  • 6815

【内存泄露】由Handler引发的内存泄漏的思考

前面Looper与Handler解析提到过下面这段代码会出现内存泄漏,其实在Android Studio中会提示这个问题: 在编辑器里面会自动将这段代码标出来,我们看看提示信息是什么?This ...
  • hp910315
  • hp910315
  • 2015-07-26 20:02
  • 2942

浅析Handler引起的内存泄漏及解决方法

在进行异步操作时,我们经常会使用到Handler类。最常见的写法如下。 public class MainActivity extends Activity { ...... pr...
  • ruancoder
  • ruancoder
  • 2016-09-06 11:52
  • 3265

浅析Handler引起的内存泄漏及解决方法

在进行异步操作时,我们经常会使用到Handler类。最常见的写法如下。 [java] view plain copy public class MainAc...
  • qq_31097291
  • qq_31097291
  • 2017-05-26 10:09
  • 120

Android-浅析Android消息处理机制使用不当造成的内存泄漏

一.Handler使用不当造成的内存泄漏内存泄漏危害极其严重,会造成OOM,使应用闪退。一般不容易发现,需要借助RefWatcher工具来进行检测。至于RefWatcher的使用方法,在这里本文就不再...
  • u012006926
  • u012006926
  • 2016-11-13 16:15
  • 281

C++程序设计内存泄漏浅析

  • 2010-05-31 14:34
  • 71KB
  • 下载

常见内存泄漏与对策及预防措施浅析

  • 2010-07-02 08:52
  • 58KB
  • 下载

Android--Handler的内存泄漏原因及解决方法

一、如何造成内存泄漏: 1、主线程的Looper对象会伴随该应用程序的整个生命周期 2、Java里,非静态内部类和匿名类都会潜在引用它们所属的外部类 发送的延迟空消息(EmptyMessageD...
  • chaoyu168
  • chaoyu168
  • 2018-01-10 15:59
  • 30

Android实战技巧之三十八:Handler使用中可能引发的内存泄漏

问题描述曾几何时,我们用原来的办法使用Handler时会有下面一段温馨的提示:This Handler class should be static or leaks might occur下面是更详...
  • lincyang
  • lincyang
  • 2015-07-14 11:20
  • 8111

Handler 内存泄漏问题

Handler 非静态内部类会持有外部类的一个隐式引用 Handler 对象会因为被MessageQueue持有引用 不能被 GC回收, handler 对象有持有 Activity的一个隐士引...
  • zidigua
  • zidigua
  • 2016-12-12 11:57
  • 90
    个人资料
    • 访问:553次
    • 积分:24
    • 等级:
    • 排名:千里之外
    • 原创:2篇
    • 转载:0篇
    • 译文:0篇
    • 评论:0条
    文章存档