Android高效加载Bitmap及缓存机制
在Android系统中,由于Bitmap的特殊性以及Android对单个应用施加的内存限制等因素,导致加载Bitmap时很容易出现内存溢出问题,即所谓的OOM。那么,如何高效加载Bitmap来降低内存占有便成为了一个重要的话题。此外,在实际开发工作中也需要对Bitmap做缓存,通过缓存策略,可极大的提高图片加载效率和用户体验。
高效加载Bitmap
在介绍高效加载Bitmap之前,你首先需要知道如何来加载Bitmap。在Android系统中,Bitmap对应一张图片,通过BitmapFactory类来实现加载;BitmapFactory提供了四类方法:decodeFile、decodeResource、decodeStream、decodeByteArray,分别用于从文件、资源、输入流和字节数组中加载出Bitmap对象,其中decodeFile、decodeResource会调用decodeStream方法来实现加载,这些方法最终会调用Android底层实现,对应着BitmapFactory的native方法。
了解了Bitmap的加载,下面来说说如何实现高效加载?核心思想是采用BitmapFactory.Options按需加载需要尺寸的Bitmap。假设我们用ImageView来显示Bitmap,通常情况下,ImageView的尺寸并没有原始图片的尺寸大,如果将图片完整加载进来后放入到ImageView中,ImageView只会显示自身大小,这样会造成内存的浪费;通过BitmapFactory.Options就可以按一定的采样率来加载缩小后的图片,将缩小后的Bitmap放入到ImageView中显示会节省很多内存,因此在一定程度上可以提高Bitmap的加载性能,避免出现OOM;BitmapFactory加载图片的四类方法都支持BitmapFactory.Options参数。先来看下BitmapFactory.Options关键代码:
public static class Options {
public Options() {
inScaled = true;
inPremultiplied = true;
}
...
public Bitmap inBitmap;
public boolean inJustDecodeBounds; //设置为true,解析图片原始宽高,不加载
public int inSampleSize; //采样率
public int outWidth; //bitmap的宽度
public int outHeight; //bitmap的高度
...
采用BitmapFactory.Options来缩放图片,主要用到inJustDecodeBounds和inSampleSize(采样率)参数,当inSampleSize=1时,缩放后的图片大小和原始图片一样大,当inSampleSize值大于1且为正整数n是,缩放后的图片大小是原始图片的1/(n*n),也就是缩放后的图片宽和高的像素分别为原始图片的1/n,比如inSampleSize=4,缩放后的图片大小是原始图片的1/16;另外根据官方文档所示,inSampleSize取值需是2的指数,否则系统会向下取整取最接近的2的指数来代替。至于inJustDecodeBounds参数的作用,如果inJustDecodeBounds为true,BitmapFactory只会去解析原始图片的大小而不会真