由于 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 开发艺术探索》




更多相关文章

  1. Android的图片浏览源码解读
  2. android的selector,背景选择器
  3. Android(安卓)开机图片/文字/动画的修改
  4. IKNinePhotoView 是一个开源的 Android(安卓)九宫格控件,可以自适
  5. Android(安卓)Opencv 之 Android(安卓)Studio 进行 opencv ( 4.2.
  6. Android(安卓)Bitmap 的加载和 Cache 缓存 笔记
  7. Android(安卓)【手撕Glide】--Glide缓存机制(面试)
  8. android 手机logo 的设置
  9. ionic 开发小问题集锦

随机推荐

  1. Android(安卓)OkHttp(1)
  2. AS升级到3.1.1之后【ZXingScannerView 二
  3. android:ContentProvider
  4. 【移动开发】Android(安卓)Animation 动
  5. Android数据存储之SQLCipher数据库加密
  6. Android之通过HTTP协议向服务器发送XML数
  7. Android模拟按键——源码环境下开发应用
  8. Android(安卓)Studio导入项目
  9. android studio 配置Kotlin环境
  10. [android sqlite]cursor读取数据表行列里