Android 图片高效加载

    由于 Bitmap 的特殊性和 Android 对于每一个应用所施加的内存限制,就会导致加载图片可能会出现 OOM 内存溢出,所有要如何高效加载一个图片是很重要的。

    那么在 Android 如何加载一个图片呢?BitmapFactory 类提供了四种方法:decodeFile、decodeResource、decodeStream、decodeByteArray。从它们名字我们就可以看出,它们分别支持从文件系统、资源、输入流和字节数组中加载 Bitmap 对象,其中 decodeFile 和 decodeResource 又间接调用了 decodeStream。

    那么如何高效加载图片呢?核心思想就是使用  BitmapFactory.Options 来加载所需尺寸的图片。例如当使用 ImageView 加载图片,当图片原始尺寸比 ImageView 大时,就需要使用 BitmapFactory.Options 将图片以一种比例缩小。这样加载缩小的图片展现到 ImageView 上,就可以降低内存在一定程度上避免 OOM。

    通过 BitmapFactory.Options 来缩放图片,主要是利用了它的 inSampleSize 参数,即采样率。当 inSampleSize 为1时,图片为原图大小,当 inSampleSize = n(n>1) 时,图片高宽均为原来的 1/n,像素为原来的 1/(n*n),内存也为原来的 1/(n*n)。

    如果,ImageView 和 Bitmap 高宽是相同的比率,那么直接缩放基本上没有问题,但是如果比率不同,图片缩放得稍小就会被拉伸导致模糊。

  • 如何获取采样率

  1.     将 BitmapFactory.Options 的 inJustDecodeBounds(此参数为 true 时,BitmapFactory 只会解析图片的原始高宽,而不会加载,所以是一个轻量级操作)参数设为 true,并加载图片。
  2. 从 BitmapFactory.Options 中取出的原始高宽对应为 outWidth、outHeight。
  3. 利用采样率规则和 VIew 的所需大小计算采样率 inSampleSize  。
  4. 将 BitmapFactory.Options 的 inJustDecodeBounds 设为 false,重新加载图片。
public static Bitmap decodeSampleBitmapFromResources(Resources res,int resId
            ,int reqWidth,int reqHeight){
        final BitmapFactory.Options options = new BitmapFactory.Options();
        //设置 inJustDecodeBounds 参数为true,解析原图
        options.inJustDecodeBounds = true;
        //加载原图
        BitmapFactory.decodeResource(res,resId,options);
        //获取采样率
        options.inSampleSize = calculateInSampleSize(options,reqWidth,reqHeight);
        //设置 inJustDecodeBounds 参数为false,不解析原图
        options.inJustDecodeBounds = false;
        //返回压缩后的图片
        return BitmapFactory.decodeResource(res,resId,options);
    }

    public static int calculateInSampleSize(BitmapFactory.Options options,int reqWidth,int reqHeight){
        //获取图片原始的宽高
        final int height = options.outHeight;
        final int width = options.outWidth;
        int inSampleSize = 1;
        //先判断图片是否需要压缩
        if (height > reqHeight || width > reqWidth){
            final int halfHeight = height/2;
            final int halfWidth = height/2;
            //直到压缩到比需要大小小
            while ((halfHeight / inSampleSize)>= reqHeight
                    && (halfWidth / inSampleSize)>= reqWidth){
                inSampleSize*=2;
            }
        }
        return inSampleSize;
    }

   当我们需要高效加载图片时,可以就直接调用 decodeSampleBitmapFromResources()方法。而BitmapFactory的其它三个方法也是试用的。

    大家如果感兴趣可以看我下一篇 Android 缓存策略

学习自《Android 开发艺术探索》




猜你喜欢

转载自blog.csdn.net/young_time/article/details/80289189