Android图片缓存策略(一)-图片加载方式

1 图片加载方式

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

2 如何高效加载BitMap

如何高效地加载Bitmap呢?其实核心思想也很简单,那就是采用BitmapFactory. Options来加载所需尺寸的图片。

这里假设通过ImageView来显示图片,很多时候ImageView并没有图片的原始尺寸那么大,这个时候把整个图片加载进来后再设给ImageView,这显然是没必要的,因为ImageView并没有办法显示原始的图片。通过BitmapFactory.Options就可以按一定的采样率来加载缩小后的图片,将缩小后的图片在ImageView中显示,这样就会降低内存占用从而在一定程度上避免OOM,提高了Bitmap加载时的性能

通过BitmapFactory.Options来缩放图片,主要是用到了它的inSampleSize参数,即采样率。

2.1 采样率说明:

设置inSanmpleSize2,则图片的宽高都会变成原来的1/2,则像素数为原图的1/4,其占的内存也为原图的1/4

inSampleSize必须是大于1的整数图片才会有缩小的效果,并且采样率同时作用于宽/高,这将导致缩放后的图片大小以采样率的2次方形式递减,即缩放比例为1/(inSampleSize的2次方),比如inSampleSize为4,那么缩放比例就是1/16。有一种特殊情况,那就是当inSampleSize小于1时,其作用相当于1,即无缩放效果

2.2 采样率获取

通过采样率即可有效地加载图片,那么到底如何获取采样率呢?获取采样率也很简单,遵循如下流程:
(1)将BitmapFactory.Options的inJustDecodeBounds参数设为true并加载图片。
(2)从BitmapFactory.Options中取出图片的原始宽高信息,它们对应于outWidthoutHeight参数。
(3)根据采样率的规则并结合目标View的所需大小计算出采样率inSampleSize
(4)将BitmapFactory.OptionsinJustDecodeBounds参数设为false,然后重新加载图片

这里说明一下inJustDecodeBounds参数,当此参数设为true时,BitmapFactory只会解析图片的原始宽/高信息,并不会去真正地加载图片,所以这个操作是轻量级的

这个时候BitmapFactory获取的图片宽/高信息和图片的位置以及程序运行的设备有关,比如同一张图片放在不同的drawable目录下或者程序运行在不同屏幕密度的设备上,这都可能导致BitmapFactory获取到不同的结果,之所以会出现这个现象,这和Android的资源加载机制有关。后面会单独再写一篇关于Android图片资源加载机制的文章

2.3 采样率计算方式

  public static int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) {
        // Raw height and width of image           
        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 = width / 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 ((halfHeight / inSampleSize) >= reqHeight&& (halfWidth / inSampleSize) >= reqWidth){
                inSampleSize *= 2;
            }
        }
        return inSampleSize;
    }

你可能感兴趣的:(Android图片缓存策略(一)-图片加载方式)