Bitmap 的高效加载

Bitmap 的高效加载_第1张图片
配图



由于bitmap的特殊性以及Android对应用所施加的内存限制,导致加载bitmap的时候很容易出现内存溢出。下面这个异常信息在开发中应该时常遇到:

java.lang.OutofMemoryError : bitmap size exceeds VM budget

因此高效地加载bitmap是一个很重要也很容易被开发者忽视的问题。

1.如何高效加载bitmap

BitmapFactory类提供了四类方法:decodeFile,decodeResource,decodeStream 和 decodeByteArray ,分别用于支持文件系统,资源,输入流,及字节数组中加载出一个Bitmap对象,其中decodeFile 和 decodeResource 又间接调用了decodeStream方法,这四类方法最终是在android底层实现的,对应着BitmapFactory类的几个native方法。

如何高效的加载Bitmap ?  那就是采用BitmapFactory.options来加载所需尺寸的图片。通过BitmapFactory.Options就可以按一定的采样率加载缩小后的图片,将缩小后的图片在ImageView中显示,这样就会降低内存的占用从而在一定程度上避免OOM。

2.什么是采样率

通过BitmapFactory.Options来缩放图片,主要是用到了它的inSampleSize参数,即采样率。当inSampleSize为1时,采样后的图片大小为原始大小,当inSampleSize大于1时,比如2,那么采样后的图片其宽高均为原图大小的1/2,像素数为原图的1/4,占有内存的大小也为原图的1/4。有一种特殊情况,当inSampleSize小于1时,其作用相当于1,即无缩放效果。另外官方文档指出,inSampleSize的值应该总是为2的指数,比如:1,2,4,8,16 等等。如果未见传递的inSampleSize 不为2的指数,那么系统会向下取整并选择一个最接近的2的指数来代替。

3.采样流程

(1)将BitmapFactory.Options的inJustDecodeBounds参数设为true并加载图片。

(2)从BitmapFactory.Options中取出图片的原始宽高信息。他们对应于outWidth 和 outHeight 参数。

(3)根据采样率的规则并结合目标View的所需大小计算出采样率inSampleSize.

(4)将BitmapFactory.Options的inJustDecodeBounds 参数设为false,然后重新加载图片。

4.采样流程实现程序

public static Bitmap decodeSampledBitmapFromResource(Resources res ,int resId, int                reqWidth, int reqHeight){

    final BitmapFactory.Options options = new BitmapFactory.Options();

    options.inJustDecodeBounds = true;

    BitmapFactory.decodeResource(res, resId, options);

    options.inJustDecodeBounds  = false;

    return BitmapFactory.decodeResource(res, resId, options);

}

public static int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight){

    final int width = options.outWidth;

    final int height = options.outHeight;

    int inSampleSize = 1;

    if(height > reqHeight || width > reqWidth){

         final int halfHeight = height/2;

         final int halfWidth = width/2;

        while((halfHeight /inSampleSize) >reqHeight

               && (halfWidth /inSampleSize) >halfWidth){

              inSampleSize *=2;

              }

      }

      return inSampleSize;

}


PS: 本文是对《Android 开发艺术探索》一书的阅读笔记,想了解原文 请自行搜索。

你可能感兴趣的:(Bitmap 的高效加载)