Bitmap的加载和Cache(存储)

版权声明:本文为博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/mashihao123/article/details/52891085

Bitmap 的加载和Cache

Bitmap的高效加载(图片的压缩)

OOM

由于Bitmap的特殊性以及Android对单个应用所施加的内存限制,比如16M这导致加载Bitmap的时候很容易就出现内存溢出.
java.lang.OutofMemoryError:bitmap size exceeds VM budget

所以我们需要多图片进行压缩,这样就不会占用多余的内存空间.

如何加载一张图片

Bitmap在Android中指的是一张图片,比如JGP,PNG,以及其他的格式的图片. 
BitmapFactory 类提供了四类方法,
  1. decodeFile 文件系统
  2. decodeResource 资源
  3. decodeStream 输入流
  4. decodeByteArray 字节数组

如何高效的加载一张图片呢

核心思想就是,采用BimapFactory.Options来加载图片所需的尺寸的图片. 将缩小后的图片在ImageView中显示,这样就降低内存占用率,从而一定程度上避免OOM

BitmapFactory.Options 主要用到了inSampleSize(采用率)

  • inSampleSize==1 原图显示
  • inSampleSize==2 宽高为原来的1/2 , 图片为原来的1/4

    inSmpleSize 只能是1,2,4,8,16, 2的指数,如果不是的话就去最接近2的指数的数值.

如何获取采用率?

  1. 将BitmapFactory.Options的inJustDecodeBounds参数设为true并加载图片
  2. 从BitmapFactory.Options中取出图片的原始宽高信息,他们对应于outWidth和outHeight参数
  3. 根据采样率的规则并结合目标View的所需大小计算出采样率
  4. 将BitmapFactory.Options 的 inJustDecodeBounds 的参数设置为false,然后重新加载图片
//可以直接当作工具类来使用
public class BitmapResizer {

    private static final String TAG = "BitmapResizer";

    public BitmapResizer() {
    }


    /**
     * TODO 通过Resource资源,来加载缩放图片.
     * @author msh
     * @time 2016/10/22 11:13
     *
    */
    public Bitmap decodeSampledBitmapFromResource(Resources res,
                                                  int resId, int reqWidth, int reqHeight) {
        final BitmapFactory.Options options = new BitmapFactory.Options();

        //1,将BitmapFactory.Options的inJustDecodeBounds参数设为true并加载图片
        options.inJustDecodeBounds = true;
        BitmapFactory.decodeResource(res, resId, options);


        //2,从BitmapFactory.Options中取出图片的原始宽高信息,他们对应于outWidth和outHeight参数
        //3,根据采样率的规则并结合目标View的所需大小计算出采样率

        // 计算 inSampleSize
        options.inSampleSize = calculateInSampleSize(options, reqWidth,
                reqHeight);

        //4, 将BitmapFactory.Options 的 inJustDecodeBounds 的参数设置为false,然后重新加载图片
        options.inJustDecodeBounds = false;
        return BitmapFactory.decodeResource(res, resId, options);
    }


/**
 * TODO 从文件系统加载图片
 * @author msh
 * @time 2016/10/22 11:15
*/
    public Bitmap decodeSampledBitmapFromFileDescriptor(FileDescriptor fd, int reqWidth, int reqHeight) {
        // First decode with inJustDecodeBounds=true to check dimensions
        final BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = true;
        BitmapFactory.decodeFileDescriptor(fd, null, options);

        // Calculate inSampleSize
        options.inSampleSize = calculateInSampleSize(options, reqWidth,
                reqHeight);

        // Decode bitmap with inSampleSize set
        options.inJustDecodeBounds = false;
        return BitmapFactory.decodeFileDescriptor(fd, null, options);
    }

    /**
     * TODO 通过计算获取图片的采用率 inSampleSize
     *
     * @param reqHeight ImageView的高
     * @param reqWidth  ImageView的宽
     * @author msh
     * @time 2016/10/22 11:02
     */
    public int calculateInSampleSize(BitmapFactory.Options options,
                                     int reqWidth, int reqHeight) {

        if (reqWidth == 0 || reqHeight == 0) {
            return 1;
        }
        //图片原始的  height   width
        final int height = options.outHeight;
        final int width = options.outWidth;

        Log.d(TAG, "origin, w= " + width + " h=" + height);
        int inSampleSize = 1;

        if (height > reqHeight || width > reqWidth) {
            final int halfHeight = height / 2;
            final int halfWidth = width / 2;

            //计算最大的inSampleSize的值,
            //通过不断的循环,最终使得图片压缩后的宽高都小于ImageView的宽高
            while ((halfHeight / inSampleSize) >= reqHeight && (halfWidth / inSampleSize) >= reqWidth) {
                inSampleSize *= 2;
            }
        }

        Log.d(TAG, "sampleSize:" + inSampleSize);
        return inSampleSize;
    }

}
展开阅读全文

没有更多推荐了,返回首页