转载请附原文链接: Volley 中的ImageLoader源码学习笔记
本篇笔记建立在上一篇分析 Volley 源码的基础上,如果你对 Volley 的源码还不了解可以看看上一篇笔记, 传送门
在 Android 中还有一大头疼的问题就是图片的加载, Volley 中封装了一个 ImageLoader 的类可以用来加载图片。本篇笔记就来分析一下 Volley 是如何处理图片加载的。
主要涉及的类:
- ImageLoader (Volley中的)
- ImageRequest
创建 ImageLoader
使用首先要创建一个 ImageLoader 对象,传入一个 请求队列,和一个 ImageCache。
|
ImageCache 是一个接口,里面有两个方法,一个从缓存中获取图片,另一个将图片放入缓存中。
|
作者在这里写了一个注释,建议使用 LruCache 来实现这个接口。
ImageCache 作为三级缓存中的第一级缓存,也就是内存缓存
获取图片
通过 get() 方法可以传入一个图片的 url 并通过 ImageListener 来获取图片。这里再提一嘴,Volley 的作者注释真的写得很清楚啊,基本上把逻辑都说的很明白。这个方法要求在主线程调用,因为显示图片需要在主线程嘛
|
如果没有在一级缓存中获取到图片会创建一个请求
|
当成功获取到图片后,首先把图片放到内存缓存中去
|
接下来就是将图片发送到各个监听中去。
|
ImageContainer 图片数据容器
一次加载图片会出现多种情况,可能从三级缓存中的任意一级中获取,这样就会有多种数据,因此封装了一个 ImageContainer 来为一次单独的加载请求持有所有的数据。
- mBitmap — 图片
- mListener — 监听
- mCacheKey — 缓存key
- mRequestUrl — 请求url
有三个方法分别是获取图片,获取url,和取消请求。
|
getImageListener 默认的监听加载
就贴个代码凑字数~没什么好说的。
|
图片的处理
我们知道在 Android 中加载图片,很容易发生 OOM 的情况,所以对图片的处理是非常有必要的。在 ImageLoader 中似乎没有看到任何处理图片的代码。实际上是在 ImageRequest 里面处理的,在拿到 Response 后就对图片进行了处理。
有时候我们可能只需要展示100*100 大小的图片,但是原图可能非常大,如果全部加载到内存中必然是浪费了空间并且可能造成内存溢出。所以我们可以根据要展示的实际大小来缩放图片,这样可以节省很大一部分内存空间。
首先科普一个小技巧,我们知道可以通过 BitmapFactory 来创建一个 Bitmap 对象,但是 BitmapFactory 会预先将这个 Bitmap 加载到内存中,实际上我们还需要对 Bitmap 进行处理,这样占用了无效的内存。BitmapFactory 在创建的时候可以传入一个 Options 对象来改变一些参数。
|
这个对象有一个属性是 inJustDecodeBounds ,从字面理解是只解码边界。这个属性设置为 true 后,BitmapFactory 返回的 Bitmap 为 null,并没有解码,但是图片的宽高等属性是可以获取到的。
|
这个技巧可以允许我们在不占用内存的情况下获取到图片的实际宽高,从而进行缩放。Options 中还有一个参数
inSampleSize — 采样率,默认为1。表示从 n 个像素中获取一个像素
这个参数需要注意几点
- 值越大,缩放越小。
- 如果这个值小于1,在处理的时候会设置为1。(因为不可能从一个像素中取半个吧,囧)
- 值尽可能接近 2 的倍数,因为如果不是 2 的倍数,在底层方法中会向下取值为 2 的倍数
知道这个技术后就可以通过图片的实际宽高和需要展示的宽高算出缩放比(采样率)
|
看看 Volley 是怎么计算目标尺寸的,这个方法传入五个参数
|
最后是计算采样率的方法,用实际的宽高分别计算比率,取最小的那个值,并且尽量接近2的倍数。
|
结语
通过学习 Volley 中的 ImageLoader 源码,对于图片的处理的理解更加深入,相信就算是自己来写图片加载,也不会有原来那么头疼。在本篇笔记中提到了 LruCache,这是 Android 官方提倡的缓存方式,因为现在对于软引用和弱饮用也会直接回收,不再可靠。在下一篇源码中将分析 LruCache 源码,看它是如果来解决缓存问题的。