Handler导致内存泄露分析
2015-04-10 15:10
211 查看
Handler导致内存泄露分析
有关内存泄露请猛戳内存泄露Handler mHandler = new Handler() { @Override public void handleMessage(Message msg) { // do something. } }
当我们这样创建
Handler的时候
Android Lint会提示我们这样一个
warning: In Android, Handler classes should be static or leaks might occur.。
一直以来没有仔细的去分析泄露的原因,先把主要原因列一下:
-
Android程序第一次创建的时候,默认会创建一个
Looper对象,
Looper去处理
Message Queue中的每个
Message,主线程的
Looper存在整个应用程序的生命周期.
-
Hanlder在主线程创建时会关联到
Looper的
Message Queue,
Message添加到消息队列中的时候
Message(排队的Message)会持有当前
Handler引用,
当
Looper处理到当前消息的时候,会调用
Handler#handleMessage(Message).就是说在
Looper处理这个
Message之前,
会有一条链
MessageQueue -> Message -> Handler -> Activity,由于它的引用导致你的
Activity被持有引用而无法被回收`
- 在java中,no-static的内部类会隐式的持有当前类的一个引用。static的内部类则没有。
具体分析
public class SampleActivity extends Activity { private final Handler mHandler = new Handler() { @Override public void handleMessage(Message msg) { // do something } } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // 发送一个10分钟后执行的一个消息 mHandler.postDelayed(new Runnable() { @Override public void run() { } }, 600000); // 结束当前的Activity finish(); }
在
finish()的时候,该
Message还没有被处理,
Message持有
Handler,
Handler持有
Activity,这样会导致该
Activity不会被回收,就发生了内存泄露.
解决方法
通过程序逻辑来进行保护。如果
Handler中执行的是耗时的操作,在关闭
Activity的时候停掉你的后台线程。线程停掉了,就相当于切断了
Handler和外部连接的线,
Activity自然会在合适的时候被回收。
如果
Handler是被
delay的
Message持有了引用,那么在
Activity的
onDestroy()方法要调用
Handler的
remove*方法,把消息对象从消息队列移除就行了。
关于
Handler.remove*方法
removeCallbacks(Runnable r)——清除r匹配上的Message。
removeC4allbacks(Runnable r, Object token)——清除r匹配且匹配token(Message.obj)的Message,token为空时,只匹配r。
removeCallbacksAndMessages(Object token)——清除token匹配上的Message。
removeMessages(int what)——按what来匹配
removeMessages(int what, Object object)——按what来匹配
我们更多需要的是清除以该
Handler为
target的所有
Message(Callback)就调用如下方法即可
handler.removeCallbacksAndMessages(null);
将
Handler声明为静态类。
静态类不持有外部类的对象,所以你的
Activity可以随意被回收。但是不持有
Activity的引用,如何去操作
Activity中的一些对象? 这里要用到弱引用
public class MyActivity extends Activity { private MyHandler mHandler; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); mHandler = new MyHandler(this); } @Override protected void onDestroy() { // Remove all Runnable and Message. mHandler.removeCallbacksAndMessages(null); super.onDestroy(); } static class MyHandler extends Handler { // WeakReference to the outer class's instance. private WeakReference<MyActivity> mOuter; public MyHandler(MyActivity activity) { mOuter = new WeakReference<MyActivity>(activity); } @Override public void handleMessage(Message msg) { MyActivity outer = mOuter.get(); if (outer != null) { // Do something with outer as your wish. } } } }
邮箱 :charon.chui@gmail.com
Good Luck!
相关文章推荐
- Handler导致内存泄露分析
- Handler导致内存泄露分析
- Handler导致内存泄露分析
- 关于DLL工程中存在全局变量可能导致MFC内存泄露误报的原因分析及解决办法
- ArrayList 与HashSet的比较,及应用反射读取properties配置文件中的数据进行实例化再调用,以及类加载器的使用;还有HashCode的分析,及导致内存泄露,内存溢出的原因之一
- 关于Android中使用Handler造成内存泄露的分析和解决
- handler为activity的成员变量导致的内存泄露
- Android中Handler导致的内存泄露
- Android中使用Handler造成内存泄露的分析和解决
- Android中使用Handler造成内存泄露的分析和解决
- Android中使用Handler造成内存泄露的分析和解决
- Android中使用Handler造成内存泄露的分析和解决
- Android中使用Handler造成内存泄露的分析和解决
- Android:Handler,内部类导致的可能内存泄露
- Android中使用Handler造成内存泄露的分析和解决
- Activity内部Handler引起内存泄露的原因分析
- Android中使用Handler造成内存泄露的分析和解决
- Android中使用Handler造成内存泄露的分析和解决
- Android中使用Handler造成内存泄露的分析和解决
- Android中使用Handler造成内存泄露的分析和解决