避免内存泄露的一些简单方法

之前的文章中说到了Android的内存管理相关的原理,也能了解到Android Memory Leak 和 OOM为什么会发生。这次主要说说编码层面,如何来预防Memory Leak的发生。

对象都是有生命周期的,对象的生命周期有的是进程级别的,有的是Activity所在的生命周期,随Activity消亡;有的是Service所在的生命周期,随Service消亡。很多情况下判断对象是否合理存在的一个很重要的理由就是它实际的生命周期是否符合它本来的生命周期。很多Memory Leak的发生,很大程度上都是生命周期的错配,本来在随Activity销毁的对象变成了进程级别的对象,Memory Leak就无法避免了。

1、常见的MemoryLeak分析

1.1 频繁的使用static关键字修饰
很多初学者非常喜欢用static类static变量,声明赋值调用都简单方便。由于static声明变量的生命周期其实是和APP的生命周期一样的(进程级别)。大量的使用的话,就会占据内存空间不释放,积少成多也会造成内存的不断开销,直至挂掉。static的合理使用一般用来修饰基本数据类型或者轻量级对象,尽量避免修复集合或者大对象,常用作修饰全局配置项、工具类方法、内部类。

1.2 BitMap隐患
Bitmap的不当处理极可能造成OOM,绝大多数情况应用程序OOM都是因这个原因出现的。Bitamp位图是Android中当之无愧的胖子,所以在操作的时候必须小心。
1.2.1 及时释放recycle。由于Dalivk并不会主动的去回收,需要开发者在Bitmap不被使用的时候recycle掉。
1.2.2 设置一定的压缩率。需求允许的话,应该去对BItmap进行一定的缩放,通过BitmapFactory.Options的inSampleSize属性进行控制。如果仅仅只想获得Bitmap的属性,其实并不需要根据BItmap的像素去分配内存,只需在解析读取Bmp的时候使用BitmapFactory.Options的inJustDecodeBounds属性。
1.2.3最后建议大家在加载网络图片的时候,使用软引用或者弱引用并进行本地缓存,推荐使用android-universal-imageloader或者xUtils。

1.3 页面背景图
在布局和代码中设置背景和图片的时候,如果是纯色,尽量使用color;如果是规则图形,尽量使用shape画图;如果稍微复杂点,可以使用9patch图;如果不能使用9patch的情况下,针对几种主流分辨率的机型进行切图。

1.4 View缓存
在ListView和GridView中,列表中的很多项(convertView)是可以重用的,不需要每次getView就重新生成一项。另外,页面的绘制其实是很耗时的,findViewById也比较慢。所以不重用View,在有列表的时候就尤为显著了,经常会出现滑动很卡的现象。

1.5 引用地狱
Activity中生成的对象原则上是应该在Activity生命周期结束之后就释放的。Activity对象本身也是,所以应该尽量避免有appliction进程级别的对象来引用Activity级别的对象,如果有的话也应该在Activity结束的时候解引用。如不应用applicationContext在Activity中获取资源。
Service也一样。

1.6 BroadCastReceiver、Service 解绑
绑定广播和服务,一定要记得在不需要的时候给解绑。

1.7 handler 清理
在Activity的onDestroy方法中调用handler.removeCallbacksAndMessages(null);取消所有的消息的处理,包括待处理的消息;

1.8 Cursor及时关闭
在查询SQLite数据库时,会返回一个Cursor,当查询完毕后,及时关闭,这样就可以把查询的结果集及时给回收掉。

1.9 I/O流
I/O流操作完毕,读写结束,记得关闭。

1.10 线程
线程不再需要继续执行的时候要记得及时关闭,开启线程数量不易过多,一般和自己机器内核数一样最好,推荐开启线程的时候,使用线程池。

1.11 String/StringBuffer
当有较多的字符创需要拼接的时候,推荐使用StringBuffer。

2、总结

如果以上做的都比较完美了,可以肯定你的程序会运行的非常好。

当然,有的时候我们也会为了程序的效率性能把本来是Activity级里才用的资源提升到进程级别,比如ImageCache,或者其它DataManager等。

我只能说,空间和时间是相对的,有的时候需要牺牲时间换取空间,有的时候需要牺牲空间换取时间。内存是空间的存在,性能是时间的存在。完美的程序是在一定条件下的完美。

时间: 2024-10-15 21:30:22

避免内存泄露的一些简单方法的相关文章

C++内存泄露的有效预防方法:谁使用,谁删除

内存泄露就是new出来的东西没有delete,我们可以这样:创建动态对象的人尽管使用new来创建对象:使用此对象的人负责释放此内存块. 例如:我和他人共享一个消息队列,他人将消息(new出来的对象)放到消息队列中,他不负责释放:我从消息队列里取消息,我一旦从消息队列里取出一个消息,消息队列里就不再有这个消息,消息的控制权和所有权都在我手上,我在用完之后就应该delete.这样就保证了代码编写的简单话,只要大家都尊周这个简单的方法就可以保证没有内存泄露. 再例如:ACE中有个ACE_Message

C++内存泄露的有效预防方法:谁使用,谁删除 (1.2)

内存泄露就是new出来的东西没有delete,我们能够这样:创建动态对象的人虽然使用new来创建对象:使用此对象的人负责释放此内存块. 比如:我和他人共享一个消息队列,他人将消息(new出来的对象)放到消息队列中,他不负责释放:我从消息队列里取消息,我一旦从消息队列里取出一个消息,消息队列里就不再有这个消息,消息的控制权和全部权都在我手上,我在用完之后就应该delete.这样就保证了代码编写的简单话,仅仅要大家都尊周这个简单的方法就能够保证没有内存泄露. 再比如:ACE中有个ACE_Messag

一种内存泄露检查和定位的方法

一个系统后台服务进程,可能包括多个线程,在生成环境下要求系统程序能够稳定长时间稳定运行而不宕机.其中一个基本的前提就是需要保证系统程序不存在内存泄露.那么,该如何判读系统程序是否存在内存泄露呢?如果存在,又该如何检测呢? 0.判读系统程序是否存在内存泄露 对于频繁快速申请内存的应用,可以允许下面的命令: top -p `pidof YourProgrogram` 如果看到系统内存使用率一直上身,没有下降,就说明很可能存在内存泄露. 对于申请.使用内存比较缓慢的应用程序,可以通过下面的命令,观测一

_CrtDumpMemoryLeaks报告程序中的内存泄露问题(简单示例代码)

// .h 文件 #pragma once class CConsoleDump { public: explicit CConsoleDump(LPCTSTR lpszWindowTitle = NULL); virtual ~CConsoleDump(void); public: BOOL DUMP(LPCTSTR lpszFmt, ...); BOOL ShowWindow(BOOL bShowWindow); BOOL SetWindowText(LPCTSTR lpszWindowTi

内存泄露从入门到精通三部曲之排查方法篇

内存泄露从入门到精通三部曲之排查方法篇 最原始的内存泄露测试 重复多次操作关键的可疑的路径,从内存监控工具中观察内存曲线,是否存在不断上升的趋势且不会在程序返回时明显回落.这种方式可以发现最基本,也是最明显的内存泄露问题,对用户价值最大,操作难度小,性价比极高. MAT内存分析工具 2.1 MAT分析heap的总内存占用大小来初步判断是否存在泄露 在Devices 中,点击要监控的程序. 点击Devices视图界面中最上方一排图标中的“Update Heap” 点击Heap视图 点击Heap视图

Android 源码系列之<十四>从源码的角度深入理解LeakCanary的内存泄露检测机制(下)

转载请注明出处:http://blog.csdn.net/llew2011/article/details/52958567 在上边文章Android 源码系列之<十三>从源码的角度深入理解LeakCanary的内存泄露检测机制(中)由于篇幅原因仅仅向小伙伴们讲述了在Android开发中如何使用LeakCanary来检测应用中出现的内存泄露,并简单的介绍了LeakCanary的相关配置信息.根据上篇文章的介绍我们知道LeakCanary为了不给APP进程造成影响所以新开启了一个进程,在新开启的

Context使用不当造成内存泄露

一般来说,视频同步指的是视频和音频同步,也就是说播放的声音要和当前显示的画面保持一致.想象以下,看一部电影的时候只看到人物嘴动没有声音传出:或者画面是激烈的战斗场景,而声音不是枪炮声却是人物说话的声音,这是非常差的一种体验. 现在游戏市场分为,pc端,移动端,浏览器端,而已移动端和浏览器端最为接近.都是短平快的特殊模式,不断的开服,合服,换皮.如此滚雪球! 那么在游戏服务器架构的设计方面肯定是以简单,快捷,节约成本来设计的. http://www.cnblogs.com/nsrtuj/ 最近接到

Android 内存泄露总结(附内存检测工具)

https://segmentfault.com/a/1190000006852540 主要是分三块: 静态储存区:编译时就分配好,在程序整个运行期间都存在.它主要存放静态数据和常量. 栈区:当方法执行时,会在栈区内存中创建方法体内部的局部变量,方法结束后自动释放内存. 堆区:通常存放 new 出来的对象.由 Java 垃圾回收器回收. 栈与堆的区别 栈内存用来存放局部变量和函数参数等.它是先进后出的队列,进出一一对应,不产生碎片,运行效率稳定高.当超过变量的作用域后,该变量也就无效了,分配给它

分析内存泄露问题

转自:http://rayleeya.iteye.com/blog/1956638 无论怎么小心,想完全避免 bad code 是不可能的,此时就需要一些工具来帮助我们检查代码中是否存在会造成内存泄漏的地方. 既然要排查的是内存问题,自然需要与内存相关的工具,DDMS和MAT就是两个非常好的工具.下面详细介绍. 2.3.1 内存监测工具 DDMS --> Heap Android tools 中的 DDMS 就带有一个很不错的内存监测工具 Heap(这里我使用 eclipse 的 ADT 插件,