解决Handler导致的内存泄漏真实样例
来源:互联网 发布:大数据 云计算 关系 编辑:程序博客网 时间:2024/05/17 08:58
背景
最近自己项目上用了网上的AutoScrollViewPager 开源Viewpager。没怎么关注别人开源的项目一些代码质量问题, 因为潜意识上别人开源在网上的肯定是令人满意的代码。最近意识到了这种心态其实并不好,而且不利于自身技术的提升。
样例
贴这个View的内存泄漏的样例,是因为发现很多程序员们在使用一些第三方开源框架,特别是一些自定义view的特效时,会用到一些延时任务之类的,那就会用到Handler这个类。在Android中,典型的Context+Handler造成的内存泄漏现象也是常见的。来看下没有处理过之前得AutoScrollViewPager 中Handler的代码:
private class H extends Handler { @Override public void handleMessage(Message msg) { Context context = getContext(); switch (msg.what) { case MSG_AUTO_SCROLL: setCurrentItem(getCurrentItem() + 1); sendEmptyMessageDelayed(MSG_AUTO_SCROLL, intervalInMillis); break; default: super.handleMessage(msg); break; } } }
问题:当程序进入handlerMessage的时候,可能context所在的Activity,Fragment已经关闭,那么因为Handler的存在,因为Handler new出来后是和当前线程绑定在一起的, 不明白的同学可以去看看Handler,MessageQuee,Looper相关源码。所以Handler在执行handlerMessage里因为持有当前自定义view的context,导致context在Activity,Fragment关闭时候无法正常释放,造成context内存泄漏。
来看下Memory Usage在Activity关闭后给出的结果:
Objects:
Views: 16 ViewRootImpl: 1
AppContexts: 4 Activities: 1
Assets: 6 AssetManagers: 6
Local Binders: 15 Proxy Binders: 20
Parcel memory: 5 Parcel count: 23
Death Recipients: 1 OpenSSL Sockets: 0
可以看到Activity依然存活。
正确修改后:
private static class H extends Handler { private AutoScrollViewPager autoScrollViewPager; private WeakReference<AutoScrollViewPager> viewHolder; public H(AutoScrollViewPager autoScrollViewPager){ this.autoScrollViewPager = autoScrollViewPager; viewHolder = new WeakReference<AutoScrollViewPager>(autoScrollViewPager); } @Override public void handleMessage(Message msg) { if (viewHolder.get()!=null){ switch (msg.what) { case MSG_AUTO_SCROLL: autoScrollViewPager.setCurrentItem(autoScrollViewPager.getCurrentItem() + 1); sendEmptyMessageDelayed(MSG_AUTO_SCROLL, autoScrollViewPager.intervalInMillis); break; default: super.handleMessage(msg); break; } } } }
这里做了几步:
1.将Handler声明为static
2.因为在handlerMessage中无法访问外部非静态方法,所以传入autoviewpager作为成员变量
3.使用WeakReference包裹autoviewpager(context) 使程序执行完handlerMessage之后的GC回收时回收autoviewpager中的context。
看现在的Memory Usage结果:
Objects
Views: 0 ViewRootImpl: 0
AppContexts: 3 Activities: 0
Assets: 6 AssetManagers: 6
Local Binders: 13 Proxy Binders: 19
Parcel memory: 5 Parcel count: 22
Death Recipients: 1 OpenSSL Sockets: 0
分享结束,告诫自己,使用handler注意内存泄漏问题,还Android一个绿色环境。
- 解决Handler导致的内存泄漏真实样例
- Handler导致内存泄漏
- Android handler导致的内存泄漏
- Handler可能导致的内存泄漏
- Android Handler导致内存泄漏的解决方案
- 解决由Handler 引起的内存泄漏
- 解决由Handler引发的内存泄漏
- cvLoadImage导致内存泄漏的解决
- 解决rxjava导致的内存泄漏
- Handler可能导致的内存泄漏及其优化
- Handler源码详解及导致内存泄漏的分析
- Handler可能导致的内存泄漏及其优化
- 解决handler可能导致的内存泄露
- 使用handler内存泄漏解决
- 解决handler 可能发生的 内存泄漏的问题
- 关于Android handler内存泄漏问题的测试与解决
- Linux线程导致的内存泄漏分析及解决
- 利用RunTime解决由NSTimer导致的内存泄漏
- go各种初步技能
- 剑指offer 二叉树中和为某一值的路径
- SpringMVC之RequestMethod
- 关于在myeclipse中使用Hibernate遇到的问题
- 图的存储二
- 解决Handler导致的内存泄漏真实样例
- 蓝桥杯-P1103-复数运算
- 去除CSDN 博客页广告的历程
- Android学习笔记_《第一行代码》
- python性能优化指南
- Mybatis学习二之Mapper XML 文件
- GDKOI 2016划水记
- HTTP协议状态码学习
- 谷哥的小弟学后台(22)——AJAX