读书笔记之Bitmap高效加载与缓存


一Bitmap的加载

BitmapFactory提供四种方法:decodeFile,decodeResource,decodeStream,decodeByteArray,分别用于支持从文件系统,资源,输入流以及字节数组中加载出一个bitmap对象。利用BitmapFactory可以高效的加载Bitmap,主要是利用BitmapFactory.Options类加载所需尺寸的图片。在加载图片之前先将图片压缩到合适的尺寸,对于加载时消耗的内存做到了节省,避免出现OOM,提高Bitmap的性能。

压缩图片主要是用到了BitmapFactory.Options的inSampleSize参数---采样率,采样后的图片长宽均缩小它的值的倍数。内存占用缩小它值得平方倍数。inSampleSize的取值有规定,只能是2的指数1、2、4、8、16……采样的原则是,采样后,图片的宽高均不小于ImageView的宽高,否则图片会被拉伸适应ImageView,变得模糊。

采样的步骤:

1、将BitmapFactory.Options的inJustDecodeBounds参数设为true并加载图片。

2、从BitmapFactory.Options中取出图片的原始宽高(对应于options.outWidth与options.outHeight)并结合ImageView的宽高计算inSampleSize的大小。

3、将BitmapFactory.Options的inJustDecodeBounds设置为false。

当BitmapFactory.Options的inJustDecodeBounds为true时,BitmapFactory只会解析图片的宽高并不会去真正的加载图片,所以这是一种轻量级的操作。

二 Bitmap的缓存

1、LruCache

内部采用一个LinkedHashMap以强引用的方式存储外界的缓存对象,其提供了get与put方法来完成缓存的获取以及添加操作,当缓存满时,LruCache会移除较早使用的缓存对象,然后再添加新的缓存对象。LruCache是线程安全的。LruCache的初始化方法中需要最大支持内存的参数。通过Runtime.getRuntime().maxMemory()得到当前进程的最大内存,采取一定比例设置LruCache的可用内存,并重写sizeOf方法,完成Bitmap大小的计算(bitmap.getRowBytes()*bitmap.getHeight())两个内存单位保持一致。

2、DiskLruCache

用于实现存储设备缓存,即磁盘缓存,将缓存对象写进文件系统达到缓存的效果。DiskLruCache并不能通过初始化方法来创建实例,提供了open方法用于创建自身。

public static DiskLruCache open(File directory,int appVersion,int valueCount,long maxSize)

第一个参数是指磁盘缓存文件系统的存储路径,第二个参数是指应用版本号,一般设置为1,当版本号发生改变时,DiskLruCache会清空之前的所有文件。第三个参数表示单个节点所对应的数据的个数,一般设置为1,第四个参数是指缓存的总大小,DiskLruCache会清除一些缓存保证不会超过这个数值。

DiskLruCache的缓存添加是通过Editor完成的,Editor表示一个缓存对象的编辑对象,首先根据图片url所对应的key,然后根据diskLruCache.edit(key)方法来获取Editor对象,如果这个缓存对象正在被操作,那么就会返回null。图片的url是唯一值,因为之中可能会有特殊字符,所以转化为key,一般采用url的MD5(十六进制)作为key。editor.newOutputStream()方法返回该缓存对象(这里是指图片)的一个输出流,可以将网络获取的图片输入流通过之前的输出流写进缓存文件。之后要调用editor的commit方法提交写入操作。

DiskLruCache的缓存查找,也是需要将url转换成key,然后通过DiskLruCache的get方法得到SnapShot对象,接着通过SnapeShot对象即可获得缓存的文件输入流,通过输入流来获取Bitmap对象,对图片进行缩放时,采用InputStream会出问题,FileInputStream是有序的输入流,两次的调用decodeStream影响了文件流的位置属性,导致了第二次decodeStream时得到null,可以通过输入流得到文件描述符,再通过BitmapFactory.decodeFileDescriptor方法来加载一张缩放后的图片。





你可能感兴趣的:(安卓开发)