Android App 内存泄漏Handler
Android App 内存泄露之Handler
Handler也是造成内存泄露的一个重要的源头,主要Handler属于TLS(Thread Local Storage)变量,生命周期和Activity是不一致的
,Handler引用Activity会存在内存泄露。
看一下例如以下代码
/**
*
* 实现的主要功能。
* @version 1.0.0
* @author Abay Zhuang <br/>
* Create at 2014-7-28
*/
public class HandlerActivity extends Activity { private final Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
// ...
}
}; @Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mHandler.sendMessageDelayed(Message.obtain(), 60000); //just finish this activity
finish();
} }
是否您曾经也是这样用的呢。
没有问题?
Eclipse 工具有这种警告提示 警告: 
This Handler class should be static or leaks might occur (com.example.ta.HandlerActivity.1)
意思:class 使用静态声明否者可能出现内存泄露。
为啥出现这种问题呢
Handler
的生命周期与Activity 不一致
- 当Android应用启动的时候,会先创建一个UI主线程的Looper对象,Looper实现了一个简单的消息队列。一个一个的处理里面的Message对象。主线程Looper对象在整个应用生命周期中存在。
- 当在主线程中初始化Handler时。该Handler和Looper的消息队列关联(没有关联会报错的)。
发送到消息队列的Message会引用发送该消息的Handler对象,这样系统能够调用 Handler#handleMessage(Message) 来分发处理该消息。
handler
引用 Activity 阻止了GC对Acivity的回收
- 在Java中,非静态(匿名)内部类会默认隐性引用外部类对象。而静态内部类不会引用外部类对象。
假设外部类是Activity,则会引起Activity泄露 。
当Activity finish后。延时消息会继续存在主线程消息队列中1分钟。然后处理消息。而该消息引用了Activity的Handler对象,然后这个Handler又引用了这个Activity。这些引用对象会保持到该消息被处理完,这样就导致该Activity对象无法被回收,从而导致了上面说的 Activity泄露。
怎样避免修?
- 使用显形的引用,1.静态内部类。
2. 外部类
- 使用弱引用 2. WeakReference
改动代码例如以下:
/**
*
* 实现的主要功能。
*
* @version 1.0.0
* @author Abay Zhuang <br/>
* Create at 2014-7-28
*/
public class HandlerActivity2 extends Activity { private static final int MESSAGE_1 = 1;
private static final int MESSAGE_2 = 2;
private static final int MESSAGE_3 = 3;
private final Handler mHandler = new MyHandler(this); @Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mHandler.sendMessageDelayed(Message.obtain(), 60000); // just finish this activity
finish();
} public void todo() {
}; private static class MyHandler extends Handler {
private final WeakReference<HandlerActivity2> mActivity; public MyHandler(HandlerActivity2 activity) {
mActivity = new WeakReference<HandlerActivity2>(activity);
} @Override
public void handleMessage(Message msg) {
System.out.println(msg);
if (mActivity.get() == null) {
return;
}
mActivity.get().todo();
}
}
上面这样就能够了吗?
当Activity finish后 handler对象还是在Message中排队。
还是会处理消息,这些处理有必要?
正常Activitiy finish后,已经没有必要对消息处理,那须要怎么做呢?
解决方式也非常easy。在Activity onStop或者onDestroy的时候,取消掉该Handler对象的Message和Runnable。
通过查看Handler的API。它有几个方法:removeCallbacks(Runnable r)和removeMessages(int what)等。
代码例如以下:
/**
* 一切都是为了不要让mHandler拖泥带水
*/
@Override
public void onDestroy() {
mHandler.removeMessages(MESSAGE_1);
mHandler.removeMessages(MESSAGE_2);
mHandler.removeMessages(MESSAGE_3); // ... ... mHandler.removeCallbacks(mRunnable); // ... ...
}
假设上面觉的麻烦,也能够如以下:
@Override
public void onDestroy() {
// If null, all callbacks and messages will be removed.
mHandler.removeCallbacksAndMessages(null);
}
敬请期待下一章(^__^) 嘻嘻……
也能够关注我的github
Android App 内存泄漏Handler的更多相关文章
- 使用android studio检测app内存泄漏【转载】
Android开发中难免会遇到各种内存泄漏,如果不及时发现处理,会导致出现内存越用越大,可能会因为内存泄漏导致出现各种奇怪的crash,甚至可能出现因内存不足而导致APP崩溃. 一般检测android ...
- 利用Android Studio、MAT对Android进行内存泄漏检测
利用Android Studio.MAT对Android进行内存泄漏检测 Android开发中难免会遇到各种内存泄漏,如果不及时发现处理,会导致出现内存越用越大,可能会因为内存泄漏导致出现各种奇怪的c ...
- android 常见内存泄漏原因及解决办法
android常见内存泄漏主要有以下几类: 一.Handler 引起的内存泄漏. 在Android开发中,我们经常会使用Handler来控制主线程UI程序的界面变化,使用非常简单方便,但是稍不注意,很 ...
- Android防止内存泄漏以及MAT的使用
Android发生内存泄漏最普遍的一种情况就是长期保持对Context,特别是Activity的引用,使得Activity无法被销毁.这也就意味着Activity中所有的成员变量也没办法销毁.本文仅介 ...
- Android App 内存泄露之调试工具(1)
Android App 内存泄露之工具(1) 使用内存监測工具 DDMS –> Heap 操作步骤 启动eclipse后,切换到DDMS透视图,并确认Devices视图.Heap视图都是打开的, ...
- monkey测试===通过monkey测试检查app内存泄漏和cpu占用
最近一直在研究monkey测试.网上资料很多,但都是一个抄一个的.原创的很少 我把检查app内存泄漏的情况梳理一下: 参考资料: Monkey测试策略:https://testerhome.com/t ...
- Android 常见内存泄漏的解决方式
在Android程序开发中.当一个对象已经不须要再使用了,本该被回收时.而另外一个正在使用的对象持有它的引用从而导致它不能被回收.这就导致本该被回收的对象不能被回收而停留在堆内存中,内存泄漏就产生了. ...
- android性能测试内存泄漏
1.什么是内存泄漏? 适用于该系统的内存使用内存泄漏,未回复(释放),该内存可以没有事业,也不能被其他人使用使用自己. 2.出有什么差别? 内存泄漏是分配出去的内存无法回收. 内存 ...
- Android 防内存泄露handler
Android 防内存泄露handler 1.使用弱引用 WeakRefHander /** * 作者: allen on 15/11/24.感谢开源作者https://coding.net/u/co ...
随机推荐
- 引导加载程序:GRUB
计算机在启动的时候,首先由BIOS中的程序执行自检,自检通过后,就根据CMOS的配置找到第一个可启动磁盘的MBR中的Boot Loader程序(一般在启动盘的第一个物理扇区,占446字节),并把控制权 ...
- 在SharePoint 2010中部署RBS (转)
一.RBS(Remote BLOB Storage)简单介绍 在SharePoint的大部分企业应用案例中,SharePoint都是要承担着非常繁重的文件管理工作,这些文件类型包含了Word文档,Ex ...
- Swift - 给表格的单元格UITableViewCell添加图片,详细文本标签
表格UITableView中,每一单元格都是一个UITableViewCell.其支持简单的自定义,比如在单元格的内部,添加图片和详细文本标签. 注意UITableViewCell的style: (1 ...
- ASP.NET常被忽视的一些细节
原文:ASP.NET常被忽视的一些细节 前段时间碰到一个问题:为什么在ASP.NET程序中定时器有时候会不工作? 这个问题看起来很奇怪,代码好像也没错,但就是结果与预期不一致. 其实这里是ASP.NE ...
- CentOS下yum使用代理的设置
export后好像没用? 问题描述: CentOS yum时出现“Could not retrieve mirrorlist http://mirrorlist.centos.org/?release ...
- hdu 4034 Graph
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4034 题目分类:图论 题意:n个顶点,然后给出从i到j的最短路径长度,求至少需要哪些边 第二组样例 第 ...
- 小议common lisp程序开发流程 - Ever 17 - 博客频道 - CSDN.NET
小议common lisp程序开发流程 - Ever 17 - 博客频道 - CSDN.NET 小议common lisp程序开发流程 分类: lisp 2011-04-17 20:59 1316人阅 ...
- 【从0到1学Web前端】CSS伪类和伪元素
1.CSS中的伪类 CSS 伪类用于向某些选择器加入特殊的效果. 语法: selector : pseudo-class {property: value} CSS 类也可与伪类搭配使用 select ...
- 外语学习强烈推荐Rosetta Stone
外语学习强烈推荐Rosetta Stone 外语学习强烈推荐Rosetta Stone
- WPF-19:分享一个样式(左右滑动选中的checbox)
首先看下效果. 选中: 不选中 样式: <Style x:Key="CheckStyle" TargetType="{x:Type CheckBox}"& ...