高效加载Bitmap

Bitmap在Android中指的是一张图片,可以是png格式也可以是jpg等其他常用的图片格式.

如何加载bitmap?

BitmapFactory类提供了四个static方法: decodeFile, decodeResource, decodeStream和decodeByteArray.

Bitmap icon = BitmapFactory.decodeResource(mContext.getResources(), R.drawable.frequent_default);
高效加载bitmap的核心思想

就是通过BitmapFactory.Options类的对象, 设置合理的inSampleSize属性值, 然后把option对象传给刚提到的加载bitmap的四个static方法, 它们都支持BitmapFactory.Options这个参数.

public static Bitmap decodeResource(Resources res, int id, Options opts)

inSampleSize: 采样率
一张10241024像素的图片,假定采用ARGB8888格式存储,占内存大小为102410244, 即4MB. 如果inSampleSize为2,那么采样后的图片宽高为原来的1/2,即512512像素, 占内存大小为5125124, 即1MB.
注意两点:

  1. 设置inSampleSize值小于1时,其作用相当于1, 即无缩放效果.
  2. 官方文档建议inSampleSize值为2的指数, 即1,2,4,8,16,等等.
设置合理的inSampleSize值

考虑以下的实际情况, 假设ImageView的大小为100100像素,而图片的原始尺寸为200200,那么设置inSampleSize为2即可,如果图片原始尺寸为200300,设置inSampleSize为2,缩小后的图片尺寸是100150,设给这个ImageView也没问题, 但如果设置inSampleSize为4, 缩小后的尺寸为50*75,达不到ImageView所期望的大小, 这时候这个图片就会被拉伸从而导致模糊, 这显然不是我们所期望看到的.
获取合理的采样率也简单, 可通过如下的流程:

  1. 将BitmapFactory.Options的inJustDecodeBounds参数设为true并加载图片.
  2. 从BitmapFactory.Options中取出图片的原始宽高,它们对应于outWidth和outHeight参数.
  3. 结合目标View所需大小,计算出inSampleSize的值.
  4. 将BitmapFactory.Options的inJustDecodeBounds参数设为false,然后从新加载图片.

这里说明一下inJustDecodeBounds参数的含义,当此参数为true时,BitmapFactory只会解析图片的原始宽高信息, 并不会去真正的加载图片,所以这个操作是轻量级的.
对上面的流程用代码实现下:

public static Bitmap decodeResourceEx(Resources res, int resId, int reqWidth, reqHeight) {
    //first, decode with inJustDecodeBounds=true to check dimensions
    final BitmapFactory.Options options = new BitmapFactory.Options();
    options.inJustDecodeBounds = true;
    BitmapFactory.decodeResource(res, id, options);

    int originWidth = options.outWidth;
    int originHeight = options.outHeight;

    //calculate inSampleSize
    options.inSampleSize = calculateInSampleSize(originWidth, originHeight, reqWidth, reqHeight);

    //Decode bitmap with inSampleSize
    options.inJustDecodeBounds = false;
    return BitmapFacotry.decodeResource(res, resId, options);

}

private int calculateInSampleSize(originWidth, originHeight, reqWidth, reqHeight) {
    int inSampleSize = 1;
    if(originWidth>reqWidth || originHeight>reqHeight) {
        final int halfWidth = originWidth / 2;
        final int halfHeight = originHeight / 2;
        //calculate the largest inSampleSize value that is a power of 2 and keeps both height and width larger than the requested height and width.
        while(((halfWidth/inSampleSize) >= reqWidth) &&((halfHeight/inSampleSize) >= reqHeight)) {
            inSampleSize *= 2;
        }
    }

    return inSampleSize;
}

比如ImageView所期望的图片大小是100*100像素,这个时候就可以通过如下方式高效地加载并显示图片:

mImageView.setImageBitmap(decodeResourceEx(getResources(), R.id.myImage, 100, 100));

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