与图片有关的软件免不了要做Bitmap的管理,要不然很可能就会发生OutOfMemory(OOM)的错误,致使程序崩溃。引起这种现象的原因无非是:


1.长期保持对某个对象或数据的引用,导致java的垃圾回收器不能回收不再使用的内存空间;


2.正在使用的有效对象占用内存空间大,导致多个有效对象生成时,吃完程序所分配的内存;


一般会报这种错误:java.lang.OutOfMemoryError: bitmap size exceeds VM budget,这是因为,android系统中读取位图Bitmap时.分给虚拟机中图片的堆栈大小只有8M。所以不管是如何调用的图片,太多太大虚拟机肯定会报这个错误。(对于实际的机器来说,这个内存分配是不是很大?)


而像相册这样子的应用,最好的效果是:


1)将图片(单个资源)缩小到适当的大小,以便于同时加载多张图片;


2)就算缩小到适当的大小,我们也不能将所有图片的引用同时保存在内存中,这时候需要将部分的图片释放;


遇到这种问题的解决方案是:缩小图片+回收资源的方式,来优化内存:


尽量不要使用setImageBitmap或setImageResource或BitmapFactory.decodeResource来设置一张大图,因为这些函数在完成decode后,最终都是通过java层的createBitmap来完成的,需要消耗更多内存。因此,改用先通过BitmapFactory.decodeStream方法,创建出一个bitmap,再将其设为ImageView的 source,decodeStream最大的秘密在于其直接调用JNI>>nativeDecodeAsset()来完成decode,无需再使用java层的createBitmap,从而节省了java层的空间。如果在读取时加上图片的Config参数,可以更有效减少加载的内存,从而更有效阻止抛out of Memory异常。


另外,decodeStream直接拿的图片来读取字节码了, 不会根据机器的各种分辨率来自动适应,使用了decodeStream之后,需要在hdpi和mdpi,ldpi中配置相应的图片资源,否则在不同分辨率机器上都是同样大小(像素点数量),显示出来的大小就不对了。


1)缩小图片的方式:

InputStream is = this.getResources().openRawResource(R.drawable.pic1);
BitmapFactory.Options options=new BitmapFactory.Options();
options.inJustDecodeBounds = false;
options.inSampleSize = 10;   //width,hight设为原来的十分一
Bitmap btp =BitmapFactory.decodeStream(is,null,options);

2)回收图片的方式:

if(!bmp.isRecycle() ){
    bmp.recycle()   //回收图片所占的内存
    system.gc()  //提醒系统及时回收
}

缓存:加载图片的时候首先检测是否被缓存然后再去动作

//用来存放图片的缓存
  HashMap<Integer, Bitmap> bitmapCache = new HashMap<Integer, Bitmap>();
  //如果没有图片,或者已经存在
  if(bitmapCache.isEmpty() || !AppConst.bitmapCache.containsKey(position)){
        bitmapCache.put(position, bm);
        System.out.println("-----------inset cache---------");
  }

定义FreeBitmap函数,在activity结束的时候,调用FreeBitmap函数,回收map中的资源

private void FreeBitmap(HashMap<Integer, Bitmap> cache){
         if(cache.isEmpty()){
             return;
         }
         for(Bitmap bitmap:cache.values()){
             if(bitmap != null && !bitmap.isRecycled()){
                 bitmap.recycle();
                 System.out.println("=============recycle bitmap=======");
             }
         }
         cache.clear();
 }