Android Handler 内存泄露
2016-01-23 20:09
549 查看
内存泄露:
java中的垃圾(GC),垃圾回收的机制受java虚拟机的控制。java虚拟机会不定时的执行 System.gc();
一个本该被回收的对象A,被一个生命周期还没有完成的对象B所持有,导致该被回收的对象A无法被回收。
那么由于B对A的持有,导致了内存泄露。
PS:
对象没有在该释放的时候被释放。
android 中使用handler ,用作消息的传递。
1.在持有handler对象的类内部调用。
handler 作为内部类,在进行信息传递的时候,handler对象一直存在。当此时持有对象A的一个activity,或者fragment被用户销毁的时候。
对象A在垃圾回收机制运行的时候,发现Activity还被其他对象所持有(对象A中还有对象正在运行) 。
那此时handler的存在就导致了内存泄露。
那这种内存泄露如何解决?
问题出在activity销毁的时候,跟他有关的都要销毁,class A ,内部handler 都要销毁。
可以在activity中的销毁的时候,给class A一个消息,(调用函数,回调函数,以及其他的消息传递)将handler内部的what移除。
现将message的标示移除,然后将handler赋值为空。垃圾回收机制再次完成的时候,activity->A->handler 的持有链就会被回收。
实际场景:
在项目遇到这种情况:
当这样初始化handler的时候,android studio 会提示这样的warning
自己翻译:
如果你这样声明一个handler作为内部类,当垃圾回收机制运行的时候,这个handler就会阻止外部调用类(class A)被垃圾回收掉。
如果这个handler被looper或者MessageQueue 在主线程以外的其他现成中使用,就不会出现问题。但是当个handler被looper或者MessageQueue 在主线程使用,你就需要对这个handler的声明进行处理。像下面这样:
1.声明这个handler作为内部类.(可行,不会出现声明周期的问题)
2.外部类,当你声明这个handler的时候,使用WeakReference(弱引用) 来初始化你的handler,在使用成员class A 的成员变量的时候,使用这个WeakReference。
WeakReference: 当声明一个类采用弱引用的方式进行声明,当垃圾回收机制运行的时候,垃圾回收机制会无视 handler对class A 的持有。直接回收class A。
WeakReference:详细解释—》》》http://www.tuicool.com/articles/imyueq
可是按提示的说法是怎么用的呢 ?
这种情况下,当activity销毁的时候,由于handler持有class A 的弱引用 ,activity->A->handler中的activity ,class A 都会被回收。
此时 这种情况虽然解决了内存泄露,又会出现另外一种问题。
!!!!如果handler的生命周期还没有完成呢?<~~~~会崩溃的, crash>
因为handler已经为空了,null.
所有还是需要当activity 被销毁的时候,给class A 一个消息,移除handler中正在执行的任务,移除handler中的message.what。并将handler==null;
在继承了view对象的Class A中有一个方法,
onDetachedFromWindow
这个方法的意思是,当view与activity之间解除关系的时候,会调用这个方法。(如果使用view的时候,完成上述的内存泄露问题的时候,这是一个神技)。也就是activity 给class A 一个消息。
直接在这个方法中对handler正在进行的操作进行处理。一切都是那么的优美。
问题也就妥妥的解决了。
关于内存泄露还会有更多的场景。此处只是在开发中遇到一个场景。但是也具有一般性。
项目中内存泄露的检测:这里给大家推荐一个神器,但是具体的用法还是不熟练。
https://github.com/liaohuqiu/leakcanary-demo
中文讲解:
http://www.liaohuqiu.net/cn/posts/leak-canary-read-me/
关于内存泄露其他高人的博客
http://www.linuxidc.com/Linux/2013-12/94065.htm
欢迎大家交流~
java中的垃圾(GC),垃圾回收的机制受java虚拟机的控制。java虚拟机会不定时的执行 System.gc();
一个本该被回收的对象A,被一个生命周期还没有完成的对象B所持有,导致该被回收的对象A无法被回收。
那么由于B对A的持有,导致了内存泄露。
PS:
对象没有在该释放的时候被释放。
android 中使用handler ,用作消息的传递。
1.在持有handler对象的类内部调用。
class A{ private String temp="hander问题"; private Handler handle=new Handler(){ // handleMessage }; }
handler 作为内部类,在进行信息传递的时候,handler对象一直存在。当此时持有对象A的一个activity,或者fragment被用户销毁的时候。
对象A在垃圾回收机制运行的时候,发现Activity还被其他对象所持有(对象A中还有对象正在运行) 。
那此时handler的存在就导致了内存泄露。
class MyActivity extends Activity{ private A a= new A(); }
那这种内存泄露如何解决?
问题出在activity销毁的时候,跟他有关的都要销毁,class A ,内部handler 都要销毁。
可以在activity中的销毁的时候,给class A一个消息,(调用函数,回调函数,以及其他的消息传递)将handler内部的what移除。
mHandler.removeMessages(WhatConstants.AUDIO.DOWNLOAD_AUDIO_DONE); mHandler=null;
现将message的标示移除,然后将handler赋值为空。垃圾回收机制再次完成的时候,activity->A->handler 的持有链就会被回收。
实际场景:
在项目遇到这种情况:
class A extends View { private Handler handle=new Handler(){ // handleMessage }; @Override protected void onDetachedFromWindow() { super.onDetachedFromWindow(); mHandler.removeMessages(WhatConstants.AUDIO.DOWNLOAD_AUDIO_FILED); mHandler=null; } }
当这样初始化handler的时候,android studio 会提示这样的warning
自己翻译:
如果你这样声明一个handler作为内部类,当垃圾回收机制运行的时候,这个handler就会阻止外部调用类(class A)被垃圾回收掉。
如果这个handler被looper或者MessageQueue 在主线程以外的其他现成中使用,就不会出现问题。但是当个handler被looper或者MessageQueue 在主线程使用,你就需要对这个handler的声明进行处理。像下面这样:
1.声明这个handler作为内部类.(可行,不会出现声明周期的问题)
2.外部类,当你声明这个handler的时候,使用WeakReference(弱引用) 来初始化你的handler,在使用成员class A 的成员变量的时候,使用这个WeakReference。
WeakReference: 当声明一个类采用弱引用的方式进行声明,当垃圾回收机制运行的时候,垃圾回收机制会无视 handler对class A 的持有。直接回收class A。
WeakReference:详细解释—》》》http://www.tuicool.com/articles/imyueq
可是按提示的说法是怎么用的呢 ?
private MyHandler myHandler= new MyHandler(this); private class MyHandler extends Handler{ WeakReference<A> weakReference; public MyHandler(A a){ weakReference=new WeakReference<A>(a); } @Override public void handleMessage(Message msg) { A a= WeakReference.get(); super.handleMessage(msg); switch (msg.what){ Log.d("~~~", a.temp); } } }
这种情况下,当activity销毁的时候,由于handler持有class A 的弱引用 ,activity->A->handler中的activity ,class A 都会被回收。
此时 这种情况虽然解决了内存泄露,又会出现另外一种问题。
!!!!如果handler的生命周期还没有完成呢?<~~~~会崩溃的, crash>
因为handler已经为空了,null.
所有还是需要当activity 被销毁的时候,给class A 一个消息,移除handler中正在执行的任务,移除handler中的message.what。并将handler==null;
在继承了view对象的Class A中有一个方法,
onDetachedFromWindow
这个方法的意思是,当view与activity之间解除关系的时候,会调用这个方法。(如果使用view的时候,完成上述的内存泄露问题的时候,这是一个神技)。也就是activity 给class A 一个消息。
直接在这个方法中对handler正在进行的操作进行处理。一切都是那么的优美。
问题也就妥妥的解决了。
关于内存泄露还会有更多的场景。此处只是在开发中遇到一个场景。但是也具有一般性。
项目中内存泄露的检测:这里给大家推荐一个神器,但是具体的用法还是不熟练。
https://github.com/liaohuqiu/leakcanary-demo
中文讲解:
http://www.liaohuqiu.net/cn/posts/leak-canary-read-me/
关于内存泄露其他高人的博客
http://www.linuxidc.com/Linux/2013-12/94065.htm
欢迎大家交流~
相关文章推荐
- 使用C++实现JNI接口需要注意的事项
- Android IPC进程间通讯机制
- Android Manifest 用法
- [转载]Activity中ConfigChanges属性的用法
- Android之获取手机上的图片和视频缩略图thumbnails
- Android之使用Http协议实现文件上传功能
- Android学习笔记(二九):嵌入浏览器
- android string.xml文件中的整型和string型代替
- i-jetty环境搭配与编译
- android之定时器AlarmManager
- android wifi 无线调试
- Android Native 绘图方法
- Android java 与 javascript互访(相互调用)的方法例子
- android 代码实现控件之间的间距
- android FragmentPagerAdapter的“标准”配置
- Android"解决"onTouch和onClick的冲突问题
- android:installLocation简析
- android searchView的关闭事件
- SourceProvider.getJniDirectories