一. 避免OOM :
1.使用更加轻量的数据结构:例如,我们可以考虑使用ArrayMap/SparseArray而不是HashMap等传统数据结构(数组 加链表实现 扩容x2) ,SparseArray更加高效,在于他们避免了对key与value的自动装箱. 使用 StringBuilder 或StringBuffer 代替 String 对字符串进行操作;
减少Bitmap 对象的内存占用;inSampleSize:缩放比例,在把图片载入内存之前,我们需 要先计算出一个合适的缩放比例,避免不必要的大图载入。decode format 设置编码,:inPurgeable:设置为True时,表示系统内存不足时可以被回 收,设置为False时,表示不能被回收
xhdpi 对应文件下放置对应的图片,并且使用更小的图片;资源文件需要选择合适的文件夹进行存放
内存对象的重复利用;减少对象的创建或者采用创建对象池,处理好复用逻辑, 对常用的对象采用单例模式创建 降低内存的分配; ListView Gridview 的ConvertView 的复用;Bitmap 的复用,LRU的机制来缓存处理好的Bitmap 并对bitmap 进行压缩;
二.避免对象的内存泄漏(反复进入某个界面 内存并没有消失)
内存对象的泄漏,会导致一些不再使用的对象无法及时释放,这样一方面占用了宝贵的内存空间,很容易导致后续需要分配内存的时候,空闲空间不足而出现OOM。
1.ActivityContext 被传递到其他实例中 导致自身被引用而发生了泄漏,非静态内部类持有外部的引用,导致内存泄漏;Handler 导致Activity泄漏(如果Handler中有延迟的任务或者是等待执行的任务队列过长,都有可能因为Handler继续执行而导致Activity发生泄漏。)为了解决这个问题,可以在UI退出之前,执行remove Handler消息队列中的消息与runnable对象。或者是使用Static + WeakReference的方式来达到断开Handler与Activity之间存在引用关系的目的。Application Context而不是Activity Context对于非UI 的Context 可以使用 Application Context。 开启Activity ,广播,Service,获取资源等操作单例的持有Context 换为持有Application Context
2.打开资源的关闭 ,如数据库Cursor对象,文件流, Dialog 要关闭 ,广播要解除注册;等
- 临时创建的Bitmap的回收 ,退出显示图片的页面时,清空缓存释放内存;
4 软引用与弱引用的应用
如果一个对象只具有软引用,那么如果内存空间足够,垃圾回收器就不会回收它;如果内存空间不足了,就会回收这些对象的内存。只要垃圾回收器没有回收它,该对象就可以被程序使用。软引用可用来实现内存敏感的高速缓存。软引用可以和一个引用队列(ReferenceQueue)联合使用,如果软引用所引用的对象被垃圾回收,Java虚拟机就会把这个软引用加入到与之关联的引用队列中。
弱引用与软引用的根本区别在于:只具有弱引用的对象拥有更短暂的生命周期,可能随时被回收。而只具有软引用的对象只有当内存不够的时候才被回收,在内存足够的时候,通常不被回收。
假设我们的应用会用到大量的默认图片,比如应用中有默认的头像,默认游戏图标等等,这些图片很多地方会用到。如果每次都去读取图片,由于读取文件需要硬件操作,速度较慢,会导致性能较低。所以我们考虑将图片缓存起来,需要的时候直接从内存中读取。但是,由于图片占用内存空间比较大,缓存很多图片需要很多的内存,就可能比较容易发生OutOfMemory异常。这时,我们可以考虑使用软引用技术来避免这个问题发生。
首先定义一个HashMap,保存软引用对象。
private Map> imageCache = new HashMap>();
private Map> imageCache = new HashMap>();
public void addBitmapToCache(String path) {
// 强引用的Bitmap对象
Bitmap bitmap = BitmapFactory.decodeFile(path);
// 软引用的Bitmap对象
SoftReference softBitmap = new SoftReference(bitmap);
// 添加该对象到Map中使其缓存
imageCache.put(path, softBitmap);
}
public Bitmap getBitmapByPath(String path) {
// 从缓存中取软引用的Bitmap对象
SoftReference softBitmap = imageCache.get(path);
// 判断是否存在软引用
if (softBitmap == null) {
return null;
}
// 取出Bitmap对象,如果由于内存不足Bitmap被回收,将取得空
Bitmap bitmap = softBitmap.get();
return bitmap;
}
使用软引用以后,在OutOfMemory异常发生之前,这些缓存的图片资源的内存空间可以被释放掉的,从而避免内存达到上限,避免Crash发生。
需要注意的是,在垃圾回收器对这个Java对象回收前,SoftReference类所提供的get方法会返回Java对象的强引用,一旦垃圾线程回收该Java对象之后,get方法将返回null。所以在获取软引用对象的代码中,一定要判断是否为null,以免出现NullPointerException异常导致应用崩溃。
个人认为,如果只是想避免OutOfMemory异常的发生,则可以使用软引用。如果对于应用的性能更在意,想尽快回收一些占用内存比较大的对象,则可以使用弱引用。还有就是可以根据对象是否经常使用来判断。如果该对象可能会经常使用的,就尽量用软引用。如果该对象不被使用的可能性更大些,就可以用弱引用。