Android Handler 避免内存泄漏的用法总结
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 避免内存泄漏的用法总结的更多相关文章
- 系统剖析Android中的内存泄漏
[转发]作为Android开发人员,我们或多或少都听说过内存泄漏.那么何为内存泄漏,Android中的内存泄漏又是什么样子的呢,本文将简单概括的进行一些总结. 关于内存泄露的定义,我可以理解成这样 没 ...
- Android性能优化-内存泄漏的8个Case
1为什么要做性能优化? 手机性能越来越好,不用纠结这些细微的性能? Android每一个应用都是运行的独立的Dalivk虚拟机,根据不同的手机分配的可用内存可能只有(32M.64M等),所谓的4GB. ...
- Android studio 分析内存泄漏
以前用eclipse的时候,我们采用的是DDMS和MAT,不仅使用步骤复杂繁琐,而且要手动排查内存泄漏的位置,操作起来比较麻烦.后来随着Android studio的潮流,我也抛弃了eclipse加入 ...
- 使用 Android Studio 检测内存泄漏与解决内存泄漏问题
本文在腾讯技术推文上 修改 发布. http://wetest.qq.com/lab/view/63.html?from=ads_test2_qqtips&sessionUserType=BF ...
- Android Handler的内存泄露问题+解决方案
谈谈handler的内存泄露问题 再来看看我们的新建Handler的代码: private Handler mHandler = new Handler() { @Override public vo ...
- Android性能优化之利用LeakCanary检测内存泄漏及解决办法
前言: 最近公司C轮融资成功了,移动团队准备扩大一下,需要招聘Android开发工程师,陆陆续续面试了几位Android应聘者,面试过程中聊到性能优化中如何避免内存泄漏问题时,很少有人全面的回答上来. ...
- 利用Android Studio、MAT对Android进行内存泄漏检测
利用Android Studio.MAT对Android进行内存泄漏检测 Android开发中难免会遇到各种内存泄漏,如果不及时发现处理,会导致出现内存越用越大,可能会因为内存泄漏导致出现各种奇怪的c ...
- 使用android studio检测app内存泄漏【转载】
Android开发中难免会遇到各种内存泄漏,如果不及时发现处理,会导致出现内存越用越大,可能会因为内存泄漏导致出现各种奇怪的crash,甚至可能出现因内存不足而导致APP崩溃. 一般检测android ...
- Android内存优化(三)避免可控的内存泄漏
相关文章 Android性能优化系列 Java虚拟机系列 前言 内存泄漏向来都是内存优化的重点,它如同幽灵一般存于我们的应用当中,有时它不会现身,但一旦现身就会让你头疼不已.因此,如何避免.发现和解决 ...
随机推荐
- IOS开发之──应用之间调用(1)
iphone应用之间调用步骤: 1)在plist文件中,注册对外接口 在xcode group&files 里面,展开 resources选择<app>info.plist 鼠标右 ...
- inputstream和outputstream读写数据模板代码
//读写数据模板代码 byte buffer[] = new byte[1024]; int len=0; while((len=in.read(buffer))>0){ out.write(b ...
- Cocos2dx 截屏
void SaveScreenshot() { CCSize size = CCDirector::sharedDirector()->getWinSize(); CCRenderTexture ...
- 利用JavaScript获取页面文档内容
JavaScript的document对象包含了页面的实际内容,所以利用document对象可以获取页面内容,例如页面标题.各个表单值. <!DOCTYPE html> <html ...
- Codeforces Round #227 (Div. 2) E. George and Cards 线段树+set
题目链接: 题目 E. George and Cards time limit per test:2 seconds memory limit per test:256 megabytes 问题描述 ...
- EXT--columnWidth
在EXT 3.4API上没有查询到columnWidth这个配置项,但它却实实在在的在起作用,后来在ColumnLayout类查到它的信息: 上面的信息描述了采用了columnLayout布局的子面板 ...
- [转载]ASP.NET对路径"xxxxx"的访问被拒绝的解决方法小结
异常详细信息: System.UnauthorizedAccessException: 对路径“D:/temp1/MyTest.txt”的访问被拒绝 在windows 2003下,在运行web ...
- MongoDB { code: 18, ok: 0.0, errmsg: "auth fails" } 原因
MongoDB出现 { code: 18, ok: 0.0, errmsg: "auth fails" } 错误的原因: 1.账号密码错误 2.账号不属于该数据库
- matlab字符串操作总结
matlab字符串操作总结 字符串操作总结 char(S1,S2,…)利用给定的字符串或单元数组创建字符数组double(S)将字符串转化成ASC码形式cellstr(S)利用的给定的字符数组创建字符 ...
- windows server 2008 R2 远程连接用户数修改
设置windows server 2008 R2 远程连接用户数修改,三步搞定 1.运行(win+R)中输入tsconfig.msc 2.双击“限制每个用户只能进行一个会话”,取消这个选项负选框 3. ...