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 ...
随机推荐
- VC 中与字符串相关的宏 _T、TEXT,_TEXT、L 的作用(简单明了)
一. 在字符串前加一个L作用: 如 L"我的字符串" 表示将ANSI字符串转换成unicode的字符串,就是每个字符占用两个字节. strlen("as ...
- timeout connect 10000 # default 10 second time out if a backend is not found
timeout connect <timeout> timeout contimeout <timeout> (deprecated) Set the maximum time ...
- Android源代码分析-资源载入机制
转载请注明出处:http://blog.csdn.net/singwhatiwanna/article/details/23387079 (来自singwhatiwanna的csdn博客) 前言 我们 ...
- Java生成文件
Java生成文件 1.说明 以文件路径作为參数,推断该文件是否存在,若不存在就创建文件.并输出文件路径 2.实现源代码 /** * @Title:BuildFile.java * @Package:c ...
- 《转》Python多线程学习
原地址:http://www.cnblogs.com/tqsummer/archive/2011/01/25/1944771.html 一.Python中的线程使用: Python中使用线程有两种方式 ...
- [Cocos2d-x]解决Android平台ndk-build时不自动删除外部库
参考链接: http://blog.chinaunix.net/uid-26009923-id-3430612.html http://hi.baidu.com/hpyfei/item/52a2b21 ...
- 图像编程学习笔记1——bmp文件结构处理与显示
文本内容转载自<数字图像处理编程入门>,代码为自己实现 1.1图和调色板的概念 如今Windows(3.x以及95,98,NT)系列已经成为绝大多数用户使用的操作系统,它比DOS成功的一个 ...
- VS2010-win32下cocos2dx控制台打印的方法
在xcode中 直接使用printf 或者 cout<<""<<endl;可以直接在控制台打印 但是在VS2010 却死活不好用 真郁闷 ------ ...
- newlisp 注释生成文档
最近写了一个newlisp_armory库,用来实现一些newlisp自身不支持的操作.比如跨windows和ubuntu的目录拷贝功能等. 自己用的时候,发现没有API reference文档参考, ...
- VMware vSphere服务器虚拟化实验十五 vCenter vShield Manager
VMware vSphere服务器虚拟化实验十五 vCenter vShield Manager VMware vShield Manager是专为 VMware vCenter Server 集成 ...