Android开发经常会用到handler,但是我们发现每次使用Handler都会出现:This Handler class should be static or leaks might occur(null)这样的提示。Android lint就是为了提示我们,这样使用Handler会容易造成内存泄漏。但是你会发现其实改成static并没有什么用。因为这并没有解决这个问题的根本。

  首先,我们得确认,为什么会有内存泄漏?因为Handler是基于消息的。每次new 出Handler,都会创建一个消息队列用于处理你使用handler发送的消息,形如:handler.send***Message。由于消息的发送总是会有先来后到的区别(如果只是这样都还好,毕竟再慢也不会太久,总归可以跑完,可能会延迟个几秒),但是如果你使用的是sendMessageDelayed(Message msg, long delayMillis)或postDelayed(Runnable r, long delayMillis)等发送延迟消息的时候,那基本内存泄漏发生的概率已经在90%以上了。

我举个通常的例子,就是我们在Activity中使用handler来更新UI控件,这是比较常见的。

 public class DemoActivity extends Activity {

     private Handler mHandler; 

     protected void onCreate(Bundle savedInstanceState) {
mHandler = new Handler();      mHandler.postDelayed(new Runnable() {
       Log.i("wytings","-----------postDelayed-------");
view.setVisibility(View.GONE);
}, 50000);
...
}
  

如果我们疯狂的对这个Activity进行横屏和竖屏切换的话,那么Activity就会不断的被销毁和重建。理论上被关闭的Activity应该会再特定时候被回收,也就是我们的内存会在一定的范围内上下起伏,但是实际上,会发现消耗的内存会随着切换横屏的次数一直慢慢增加。这其实已经说明我们的内存泄漏了,如果你会查看内存,你会发现里面有成堆的DemoActivity实例没办法回收。

  这是因为view中使用的Context就是当前的Activity,而这个runnable一旦被post,就会一直存在于队列里面,直到时间到了,被执行。意思是这个时间段内Activity即使已经被destroy了但是这个对象还是没办法回收,你会发现50秒好,会有一堆"-----------postDelayed-------"的log打印出来,虽然你已经被这个应用关闭了并且你以为即使打印也应该只打印一次……

  那怎么样才可以避免这中问题呢,如果你网上一搜你会看到很多关于弱引用的文章。这确实是一个解决的办法。其原理就是让所有在handler里面使用的对象都变成弱引用,目的就是为了可以在Android回收内存的时候,可以直接回收掉。我真觉得如果只是写这种办法的人,绝对是属于拷贝党,因为这完全是就事论事。你想想就明白,我们写这个Handler是因为我们要使用它。怎么可以通过这种弱引用的办法去处理这类问题呢?让JVM想回收就回收?!如果这样,那我们还需要在使用Bitmap的时候,recycle()干嘛,还不如直接弄成软引用得了。

这里需要再插播一下关于Java里面引用的知识:

强引用(Strong Reference) 默认引用。如果一个对象具有强引用,垃圾回收器绝不会回收它。在内存空 间不足时,Java虚拟机宁愿抛出OutOfMemory的错误,使程序异常终止,也不会强引用的对象来解决内存不足问题。
软引用(SoftReference) 如果内存空间足够,垃圾回收器就不会回收它,如果内存空间不足了,就会回收这些对象的内存。
弱引用(WeakReference) 在垃圾回收器一旦发现了只具有弱引用的对象,不管当前内存空间足够与否,都会回收它的内存。
虚引用(PhantomReference) 如果一个对象仅持有虚引用,那么它就和没有任何引用一样,在任何时候都可能被垃圾回收。

如果你运气好,你会碰到一些除了写弱引用这个方法后,还有一个就是handler.removeCallbacksAndMessages(null);,就是移除所有的消息和回调,简单一句话就是清空了消息队列。注意,不要以为你post的是个Runnable或者只是sendEmptyMessage。你可以看一下源码,在handler里面都是会把这些转成正统的Message,放入消息队列里面,所以清空队列就意味着这个Handler直接被打成原型了,当然也就可以回收了。

  所以,我觉得最好的办法就是你在使用Handler的时候,在外面的Activity或者Fragment中的关闭方法中,如onDestroy中调用一下handler.removeCallbacksAndMessages(null);就可以了,不应该改成软引用。

转自:http://www.cnblogs.com/wytings/p/5225278.html

Android Handler 避免内存泄漏的用法总结的更多相关文章

  1. 系统剖析Android中的内存泄漏

    [转发]作为Android开发人员,我们或多或少都听说过内存泄漏.那么何为内存泄漏,Android中的内存泄漏又是什么样子的呢,本文将简单概括的进行一些总结. 关于内存泄露的定义,我可以理解成这样 没 ...

  2. Android性能优化-内存泄漏的8个Case

    1为什么要做性能优化? 手机性能越来越好,不用纠结这些细微的性能? Android每一个应用都是运行的独立的Dalivk虚拟机,根据不同的手机分配的可用内存可能只有(32M.64M等),所谓的4GB. ...

  3. Android studio 分析内存泄漏

    以前用eclipse的时候,我们采用的是DDMS和MAT,不仅使用步骤复杂繁琐,而且要手动排查内存泄漏的位置,操作起来比较麻烦.后来随着Android studio的潮流,我也抛弃了eclipse加入 ...

  4. 使用 Android Studio 检测内存泄漏与解决内存泄漏问题

    本文在腾讯技术推文上 修改 发布. http://wetest.qq.com/lab/view/63.html?from=ads_test2_qqtips&sessionUserType=BF ...

  5. Android Handler的内存泄露问题+解决方案

    谈谈handler的内存泄露问题 再来看看我们的新建Handler的代码: private Handler mHandler = new Handler() { @Override public vo ...

  6. Android性能优化之利用LeakCanary检测内存泄漏及解决办法

    前言: 最近公司C轮融资成功了,移动团队准备扩大一下,需要招聘Android开发工程师,陆陆续续面试了几位Android应聘者,面试过程中聊到性能优化中如何避免内存泄漏问题时,很少有人全面的回答上来. ...

  7. 利用Android Studio、MAT对Android进行内存泄漏检测

    利用Android Studio.MAT对Android进行内存泄漏检测 Android开发中难免会遇到各种内存泄漏,如果不及时发现处理,会导致出现内存越用越大,可能会因为内存泄漏导致出现各种奇怪的c ...

  8. 使用android studio检测app内存泄漏【转载】

    Android开发中难免会遇到各种内存泄漏,如果不及时发现处理,会导致出现内存越用越大,可能会因为内存泄漏导致出现各种奇怪的crash,甚至可能出现因内存不足而导致APP崩溃. 一般检测android ...

  9. Android内存优化(三)避免可控的内存泄漏

    相关文章 Android性能优化系列 Java虚拟机系列 前言 内存泄漏向来都是内存优化的重点,它如同幽灵一般存于我们的应用当中,有时它不会现身,但一旦现身就会让你头疼不已.因此,如何避免.发现和解决 ...

随机推荐

  1. php protected只能被继承,不可以在实例中调用,parent::调用父类(子类函数的重载对父类的函数没有影响)

    <?php class a { private function fun1(){ echo 'a1'; } //protected 可以被继承,但是只能在子类中使用,不能被实例化调用 prote ...

  2. Express/Koa/Hapi

    Express/Koa/Hapi 本文翻译自: https://www.airpair.com/node.js/posts/nodejs-framework-comparison-express-ko ...

  3. python学习小结5:封装、继承、多态

    面向对象程序设计中的类有三大特性: 继承,封装,多态 继承:以普通的类为基础建立专门的类对象 封装:对外部世界隐藏对象的工作细节 多态:可对不同类的对象使用同样的操作 在Python中类的继承定义基本 ...

  4. 【转】并查集&MST题集

    转自:http://blog.csdn.net/shahdza/article/details/7779230 [HDU]1213 How Many Tables 基础并查集★1272 小希的迷宫 基 ...

  5. hdu 1875 畅通工程再续(最小生成树,基础)

    题目 让人郁闷的题目,wa到死了,必须要把判断10.0和1000.0的条件放到prim函数外面去.如代码所放.... 正确的(放在prim外): //2个小岛之间的距离不能小于10米,也不能大于100 ...

  6. hdu 2481 Toy

    好题!!!没话说…… 用到的知识面很多,这题的难点在于公式的推导. 原始推导过程见:http://hi.baidu.com/spellbreaker/item/d8bb3bda5af30be6795d ...

  7. zend studio 10破解/汉化(转发)

    转发:http://blog.csdn.net/qq1355541448/article/details/16807429 Zend Studio 10正式版破解及汉化 2013年03月12日 ⁄ P ...

  8. hdu 3544 Alice's Game

    #include<stdio.h> int main() { int t,n; __int64 sum1,sum2; int i,j,a,b; scanf("%d",& ...

  9. 【Linux高频命令专题(18)】tail

    概述 tail 命令从指定点开始将文件写到标准输出.使用tail命令的-f选项可以方便的查阅正在改变的日志文件,tail -f filename会把filename里最尾部的内容显示在屏幕上,并且不但 ...

  10. emms指令在MMX指令中的作用

    emms指令在MMX指令中的作用 转自:http://blog.csdn.net/psusong/archive/2009/01/08/3737047.aspx MMX和SSE都是INTEL开发的基于 ...