一. 避免OOM :



1.使用更加轻量的数据结构:例如,我们可以考虑使用ArrayMap/SparseArray而不是HashMap等传统数据结构(数组 加链表实现 扩容x2) ,SparseArray更加高效,在于他们避免了对key与value的自动装箱. 使用 StringBuilder 或StringBuffer 代替 String 对字符串进行操作;



2.减少Bitmap 对象的内存占用;inSampleSize:缩放比例,在把图片载入内存之前,我们需 要先计算出一个合适的缩放比例,避免不必要的大图载入。decode format 设置编码,:inPurgeable:设置为True时,表示系统内存不足时可以被回 收,设置为False时,表示不能被回收



3. xhdpi 对应文件下放置对应的图片,并且使用更小的图片;资源文件需要选择合适的文件夹进行存放



4.内存对象的重复利用;减少对象的创建或者采用创建对象池,处理好复用逻辑, 对常用的对象采用单例模式创建 降低内存的分配; ListView Gridview 的ConvertView 的复用;Bitmap 的复用,LRU的机制来缓存处理好的Bitmap 并对bitmap 进行压缩;


二.避免对象的内存泄漏(反复进入某个界面 内存并没有消失)



内存对象的泄漏,会导致一些不再使用的对象无法及时释放,这样一方面占用了宝贵的内存空间,很容易导致后续需要分配内存的时候,空闲空间不足而出现OOM。



1.Activity Context 被传递到其他实例中 导致自身被引用而发生了泄漏,如非静态内部类持有外部的引用,导致内存泄漏;Handler 导致Activity泄漏(如果Handler中有延迟的任务或者是等待执行的任务队列过长,都有可能因为Handler继续执行而导致Activity发生泄漏。)为了解决这个问题,可以在UI退出之前,执行remove Handler消息队列中的消息与runnable对象。或者是使用Static +WeakReference的方式来达到断开Handler与Activity之间存在引用关系的目的



2.Application Context而不是Activity Context,对于非UI 的Context 可以使用 Application Context。 开启Activity ,广播,Service,获取资源等操作单例的持有Context 换为持有Application Context。



3.打开资源的关闭 ,如数据库Cursor对象,文件流, Dialog 要关闭 ,广播要解除注册;等临时创建的Bitmap的回收 ,退出显示图片的页面时,清空缓存释放内存;


三.软引用与弱引用的应用



1. 如果一个对象只具有软引用,那么如果内存空间足够,垃圾回收器就不会回收它;如果内存空间不足了,就会回收这些对象的内存。只要垃圾回收器没有回收它,该对象就可以被程序使用。软引用可用来实现内存敏感的高速缓存。软引用可以和一个引用队列(ReferenceQueue)联合使用,如果软引用所引用的对象被垃圾回收,Java虚拟机就会把这个软引用加入到与之关联的引用队列中。弱引用与软引用的根本区别在于:只具有弱引用的对象拥有更短暂的生命周期,可能随时被回收。而只具有软引用的对象只有当内存不够的时候才被回收,在内存足够的时候,通常不被回收。



2.假设我们的应用会用到大量的默认图片,比如应用中有默认的头像,默认游戏图标等等,这些图片很多地方会用到。如果每次都去读取图片,由于读取文件需要硬件操作,速度较慢,会导致性能较低。所以我们考虑将图片缓存起来,需要的时候直接从内存中读取。但是,由于图片占用内存空间比较大,缓存很多图片需要很多的内存,就可能比较容易发生OutOfMemory异常。这时,我们可以考虑使用软引用技术来避免这个问题发生。


首先定义一个HashMap,保存软引用对象。


   
   private
   
    Map
   
   <
   
   String
   
   ,
   
    SoftReference
   
   <
   
   Bitmap
   
   >>
   
    imageCache 
   
   =
   
    
   
   new
   
    
   
   H
   
   a
   
   shMap<
   
   S
   
   tring, SoftRef
   
   e
   
   rence<
   
   Bi
   
   t
   
   m
   
   a
   
   p>
   
   >();


   
   p
   
   ubli
   
   c
   
    void addBitmapT
   
   o
   
   Cache(Strin
   
   g
   
    
   
   p
   
   a
   
   th) {
// 强引用的Bi
   
   tmap对象
Bitmap b
   
   i
   
   tmap = BitmapF
   
   a
   
   ctory.deco
   
   d
   
   eFil
   
   e
   
   (
   
   p
   
   ath);
// 软引用的Bi
   
   tmap对象
SoftRef
   
   e
   
   rence<
   
   B
   
   itmap> softB
   
   i
   
   t
   
   map
   
    
   
   =
   
    
   
   new So
   
   f
   
   t
   
   Refere
   
   n
   
   c
   
   e
   
   <Bitmap>(bitmap);
   
   
// 添加该对象到M
   
   a
   
   p中使
   
   其
   
   缓存
i
   
   m
   
   ageCache.pu
   
   t
   
   (
   
   p
   
   a
   
   th
   
   , soft
   
   Bitmap);
   
   
}

public Bitm
   
   a
   
   p getBitmap
   
   B
   
   y
   
   P
   
   a
   
   th(String path) {
//
   
    从缓存中取软引用的Bitmap
   
   对
   
   象
  So
   
   f
   
   tReference<B
   
   i
   
   tmap> softB
   
   i
   
   tma
   
   p
   
    = i
   
   m
   
   a
   
   g
   
   eCache.get(p
   
   ath);
   
   
/
   
   /
   
    
   
   判断是否存在软引用
 
   
     
   
    if (
   
   s
   
   o
   
   f
   
   tBitmap 
   
   == nul
   
   l) {

   
    
   
        
   
    
   
   r
   
   eturn null;
    }
// 取出Bitmap对象,如果由于
   
   内存不足Bitmap被回收,将取得空

   
    
   
      Bitmap b
   
   i
   
   tma
   
   p
   
    
   
   =
   
    soft
   
   Bitmap
   
   .get();
   
   

   
    
   
    
   
     return bitmap;
}
  
  
  
  
   
   

  
  
  
  
   
   使用软引用以后,在OutOfMemory异常发生之前,这些缓存的图片资源的内存空间可以被释放掉的,从而避免内存达到上限,避免Crash发生。
   
   需要注意的是,在垃圾回收器对这个Java对象回收前,SoftReference类所提供的get方法会返回Java对象的强引用,一旦垃圾线程回收该Java对象之后,get方法将返回null。所以在获取软引用对象的代码中,一定要判断是否为null,以免出现NullPointerException异常导致应用崩溃。
  
  
  
  
   
          个人认为,如果只是想避免OutOfMemory异常的发生,则可以使用软引用。如果对于应用的性能更在意,想尽快回收一些占用内存比较大的对象,则可以使用弱引用。还有就是可以根据对象是否经常使用来判断。如果该对象可能会经常使用的,就尽量用软引用。如果该对象不被使用的可能性更大些,就可以用用弱引用。