上一期介绍了Glide的memory cache机制架构,也就是图片从内存缓存中获取的,忽略了Glide从disk中获取缓存图片,今天我们就来讲讲Glide从disk或者网络获取图片,并且一步步转化为我们ImageView可以显示的格式。同样也会先提出一些疑问,Glide中source和result缓存策略分别是什么意思?如果是本地图片,是否也会缓存到disk?图片源有那么多种格式(url, path, uri, assert, byte[]等)Glide是怎么巧妙地来处理耦合问题?
架构图
同样的,带着这么多问题,先看下图片转换的架构图
从这幅图中可以清晰看到,Glide是如何从url中获取图片, 并且转换到最后的GlideDrawable(继承自Drawable)。并且中间有两个地方有做图片的缓存,分别是source cache和result cache。看过我Glide系列第一篇文章的同学可能有印象,其中有一个GenericRequestBuild这个类,它有ModelType, DataType, ResourceType, TranscodeType这四个泛型,对于初次看Glide源码的人,这几个泛型不好理解,简直就要命了。希望在接下来中,对这个几个泛型能有更好的认识。好的,接下来就以这四个泛型为切入点详细得分解下每个转换过程。
ModelType
对于这个类型,其实是最简单的,也是Glide用户接触最为直接的参数。也就是你在调用load()方法时,传入的参数。最简单地,load(“http://xxx.jpg“)。这个时候ModelType就是String.class。当然ModelType会有很多种类型,File.class, int.class, String.class, Uri.class, URL.class, byte[].class等。你传入那么多类型的参数。Glide又是如何来进行分解处理的呢,这里就涉及到两个抽象类,ModelLoader和DataFetcher。
ModelLoader
ModelLoader是对传入数据的包装类型,比如说你传入的String.class就会被封装成StreamStringLoader, 传入File.class会封装成StreamFileLoader。这个对照可以在Glide的构造方法里面找到。然而ModelLoader存在的意义仅仅在于获得DataFetcher, 或者说获得何种类型的DataFetcher。
DataFetcher
DataFetcher是通过ModelLoader中调用getResourceFetcher()方法获取到的,它直接去获取资源了。举个例子String.class类型的ModelType传入的是url,将会得到HttpUrlFetcher。在这里面的loadData(), 会从网络下载图片,然后以InputStream返回。(这里默认使用的是HttpUrlConnection来请求图片,当然也使用自己喜欢的网络库,对于对于网络库切换以后会讲到)
DataType
在上面的DataFetcher中通过loadData()方法拿到了InputStream。这个其实也就是DataType。
ResourceType
decode
拿到InputStream后,是无法直接显示,也无法缓存的。所以需要decode()后才能缓存和进一步使用。详细的可以在DecodeJob的decodeFromSource()里面看到。decode()就是第一个过程,把InputStream(可能已经被封装为ImageVideoWrapper)转为了GifBitmapWrapper。这个时候根据事先在DiskCacheStrategy中设置的缓存策略,会把这个阶段的图片资源缓存到disk,这个时候存储的也就是source也就是原始图片的大小,但是根据默认配置,是不会缓存source的。
transform
Glide有个显著的有点就是,它可以根据ImageView的大小了加载图片,来降低内存的使用率。这个就得益于transform,这个过程中,Glide把GifBitmapWrapper中的图片转换为ImageView的宽高。并且在这一步中也有缓存。还是根据DiskCacheStrategy中设置的缓存策略,把图片缓存到disk中。这个根据默认配置就是会缓存的。
TranscodeType
为了得到可以在ImageView上展现的类型,还需要再一次转换,GifBitmapWrapper经过transcode()之后就变成GlideDrawable,可以直接显示到ImageView上了(看到源码貌似直接从GifBitmapWrapper中拿到Bitmap后再进行了一些封装,不知道为什么要多写着一个泛型)。
Glide的图片转换过程大概就是这样吧,回头看看之前的疑问,大概也都解决了。整体思路都是从源码中得出的,要是想真正了解Glide, 还是那句话,“read the fucking source code”。