转载请注明本文出自大苞米的博客(http://blog.csdn.net/a396901990),谢谢支持!java
写在最前:面试
本文的思路主要借鉴了2014年AnDevCon开发者大会的一个演讲PPT,加上把网上搜集的各类内存零散知识点进行汇总、挑选、简化后整理而成。缓存
因此我将本文定义为一个工具类的文章,若是你在ANDROID开发中遇到关于内存问题,或者立刻要参加面试,或者就是单纯的学习或复习一下内存相关知识,都欢迎阅读。(本文最后我会尽可能列出所参考的文章)。app
OOM:工具
内存泄露能够引起不少的问题:性能
1.程序卡顿,响应速度慢(内存占用高时JVM虚拟机会频繁触发GC)学习
2.莫名消失(当你的程序所占内存越大,它在后台的时候就越可能被干掉。反以内存占用越小,在后台存在的时间就越长)优化
3.直接崩溃(OutOfMemoryError)spa
ANDROID内存面临的问题:操作系统
1.有限的堆内存,原始只有16M
2.内存大小消耗等根据设备,操做系统等级,屏幕尺寸的不一样而不一样
3.程序不能直接控制
4.支持后台多任务处理(multitasking)
5.运行在虚拟机之上
5R:
本文主要经过以下的5R方法来对ANDROID内存进行优化:
1.Reckon(计算)
首先须要知道你的app所消耗内存的状况,知己知彼才能百战不殆
2.Reduce(减小)
消耗更少的资源
3.Reuse(重用)
当第一次使用完之后,尽可能给其余的使用
5.Recycle(回收)
回收资源
4.Review(检查)
回顾检查你的程序,看看设计或代码有什么不合理的地方。
Reckon:
关于内存简介,和Reckon(内存计算)的内容请看上一篇文章:ANDROID内存优化(大汇总——上)
Reduce :
Reduce的意思就是减小,直接减小内存的使用是最有效的优化方式。
下面来看看有哪些方法能够减小内存使用:
图片显示:
咱们须要根据需求去加载图片的大小。
例如在列表中仅用于预览时加载缩略图(thumbnails )。
只有当用户点击具体条目想看详细信息的时候,这时另启动一个fragment/activity/对话框等等,去显示整个图片
图片大小:
直接使用ImageView显示bitmap会占用较多资源,特别是图片较大的时候,可能致使崩溃。
使用BitmapFactory.Options设置inSampleSize, 这样作能够减小对系统资源的要求。
属性值inSampleSize表示缩略图大小为原始图片大小的几分之一,即若是这个值为2,则取出的缩略图的宽和高都是原始图片的1/2,图片大小就为原始大小的1/4。
图片像素:
图片回收:
使用Bitmap事后,就须要及时的调用Bitmap.recycle()方法来释放Bitmap占用的内存空间,而不要等Android系统来进行释放。
下面是释放Bitmap的示例代码片断。
捕获异常:
通过上面这些优化后还会存在报OOM的风险,因此下面须要一道最后的关卡——捕获OOM异常:
修改对象引用类型:
引用类型:
引用分为四种级别,这四种级别由高到低依次为:强引用>软引用>弱引用>虚引用。
强引用(strong reference)
如:Object object=new Object(),object就是一个强引用了。当内存空间不足,Java虚拟机宁愿抛出OutOfMemoryError错误,使程序异常终止,也不会靠随意回收具备强引用的对象来解决内存不足问题。
软引用(SoftReference)
只有内存不够时才回收,经常使用于缓存;当内存达到一个阀值,GC就会去回收它;
弱引用(WeakReference)
弱引用的对象拥有更短暂的生命周期。在垃圾回收器线程扫描它 所管辖的内存区域的过程当中,一旦发现了只具备弱引用的对象,无论当前内存空间足够与否,都会回收它的内存。
虚引用(PhantomReference)
"虚引用"顾名思义,就是形同虚设,与其余几种引用都不一样,虚引用并不会决定对象的生命周期。若是一个对象仅持有虚引用,那么它就和没有任何引用同样,在任什么时候候均可能被垃圾回收。
软引用和弱引用的应用实例:
注意:对于SoftReference(软引用)或者WeakReference(弱引用)的Bitmap缓存方案,如今已经不推荐使用了。自Android2.3版本(API Level 9)开始,垃圾回收器更着重于对软/弱引用的回收,因此下面的内容能够选择忽略。
在Android应用的开发中,为了防止内存溢出,在处理一些占用内存大并且声明周期较长的对象时候,能够尽可能应用软引用和弱引用技术。
下面以使用软引用为例来详细说明(弱引用的使用方式与软引用是相似的):
假设咱们的应用会用到大量的默认图片,并且这些图片不少地方会用到。若是每次都去读取图片,因为读取文件须要硬件操做,速度较慢,会致使性能较低。因此咱们考虑将图片缓存起来,须要的时候直接从内存中读取。可是,因为图片占用内存空间比较大,缓存不少图片须要不少的内存,就可能比较容易发生OutOfMemory异常。这时,咱们能够考虑使用软引用技术来避免这个问题发生。
首先定义一个HashMap,保存软引用对象。
须要注意的是,在垃圾回收器对这个Java对象回收前,SoftReference类所提供的get方法会返回Java对象的强引用,一旦垃圾线程回收该Java对象以后,get方法将返回null。因此在获取软引用对象的代码中,必定要判断是否为null,以避免出现NullPointerException异常致使应用崩溃。
到底何时使用软引用,何时使用弱引用呢?
我的认为,若是只是想避免OutOfMemory异常的发生,则可使用软引用。若是对于应用的性能更在乎,想尽快回收一些占用内存比较大的对象,则可使用弱引用。
还有就是能够根据对象是否常用来判断。若是该对象可能会常用的,就尽可能用软引用。若是该对象不被使用的可能性更大些,就能够用弱引用。
另外,和弱引用功能相似的是WeakHashMap。WeakHashMap对于一个给定的键,其映射的存在并不阻止垃圾回收器对该键的回收,回收之后,其条目从映射中有效地移除。WeakHashMap使用ReferenceQueue实现的这种机制。
其余小tips: