自从Android诞生以来,Bitmap的管理就一直是大问题,为了更好的管理它,不一样的图片加载框架不断的被推出,从刚开始的ImageLoader,到Picasso,再到如今的Fresco和Glide,可谓百花齐放。然而前二者如今都已经再也不维护了,同时咱们公司的项目目前也已经从Fresco切换到Glide了,以前之因此用Fresco是由于他在Android5.0如下系统中能从native层“偷”内存,但后面因为Android对于Bitmap内存管理方式的改变,这个功能再也不生效,相比于Glide来讲,Fresco就显得侵入性太强,并且可扩展性没有glide强。而Glide之因此扩展性如此强,就在于它 优秀的架构设计 ,这也是咱们今天要讨论的。面试
首先咱们看下Glide整体架构图:编程
从架构图上,咱们能够看出,glide并无着眼于bitmap,而是进行了高度的抽象,因此咱们不该该将glide当作一个图片加载框架,而是一个资源从不一样形态之间转换的框架,从url到bitmap只是其中一种,因此咱们不难理解glide甚至能从视频加载第一帧,由于它没有对输入类型作任何限制,都是统一抽象成的Request。设计模式
这里以从url到inputstream二进制流为例,之因此这里有三条分路,这和glide的缓存策略有关。首先有一点要澄清,这里从Request到Data实际上是跳过了内存缓存的介绍,毕竟若是内存中已有bitmap缓存,咱们直接取用就能够了,无需这么麻烦(详细的缓存方案后续文章会介绍)。所以,这里有三条路径主要是磁盘缓存和网络缓存,而磁盘缓存有两种:数组
因为glide的这种高度抽象,如今咱们面临着一个问题:如此多类型的Request和如此多的Data,具体怎么去加载它呢?好比说Request有url、uri、File、资源id、视频等等,不一样的Request确定有不一样的加载方式,同一个Request既可能从网络加载,也可能从磁盘加载,可能性太多,那么咱们怎么去加载呢?if-else去判断吗?一个优秀的框架确定不会干这种low到爆的事。这里咱们介绍一些新的角色:缓存
这里,针对每一种Request,咱们都有对应的ModelLoader,当一个Request进来时,咱们能够遍历全部的ModelLoader,经过handles()方法判断这个ModelLoader可否处理这种Request,这样咱们就能解决第一个问题,即不一样的Request如何管理加载,有了ModelLoader机制,若是咱们想增长一种Request,咱们只要开发对应的ModelLoader便可。网络
有了ModelLoader,实际上是不够的,它只是用来判断这个Request是否可否处理,为了能真正的加载请求,Glide引入了DataFetcher,不一样的方式对应一个不一样的DataFetcher,二者职责分离,这是由于同一种Request其实有不少加载方式,好比从网络加载,从磁盘加载等等,很是复杂,因此这里独立出一个DataFetcher。其中LoadData只是对DataFetcher的一种包装,多包含了一些信息而已。架构
如今,咱们根据传入的请求具体类型(好比url仍是file仍是字节数组),经过遍历全部的ModelLoader判断该ModelLoader可否处理这种请求,而后用该ModelLoader中的DataFetcher去具体加载这个请求。框架
有了ModelLoader和DataFetcher机制,Glide已经能方便的将一个原始请求从不一样的地方加载到内存中了,这个时候这份数据还只是单纯的二进制数据(携带了格式数据)而已,咱们称其为Data,如今须要进行解码过程,剔除原始的格式信息,而后拿原始信息从新编码,将其转化成不一样的格式,好比将一个jpg先解码而后转码成Bitmap,或者转码成Gif,解码以及转码后的数据咱们称其为Resource。如今面临的问题仍是同样的:ide
因为框架的设计决定了须要解码的格式是不定的,要转码的格式也是不定的,如何高效的组织这个过程呢?学习
这个和Request被加载的过程相似,这里采用的是模板方法设计模式:
能够看到,这里咱们能从Registry中获取全部的ResourceDecoder和ResourceTranscoder,而后判断哪一个解码器或转码器适合当前格式,直接调用相关的decode和transcode方法就能够了。
以这种方式,咱们能随意扩展不一样格式的解码和转码了。
资源解码并转码后,因为某些特殊的需求,咱们是不能直接使用的,好比有圆角需求,透明度需求等等,完成这步转换的,就是Transformation。因为这一步转换是可选的,和上面两步都不一样必须进过的步骤不一样,这里的Transformation就不能存在一个地方主动去取,必须是得构建这整个流程的时候指定使用哪一个Transformation,这里没有什么复杂的架构,你们了解下Transformation的大体状况便可:
如今咱们走到了最后一步,须要将符合条件的Resource显示在指定的Target上,固然具体如何显示细节本文不讨论,咱们主要关注的是显示时候的动画操做,也就是通过Transition的 transition()。这一步和上面一步相似,是否须要使用Transition和使用哪一个Transition都是由请求时用户决定的,所以这里也没有复杂架构,你们看下Transition的组成便可:
其实从整体架构上来讲,Glide的设计无疑是很是完美的,每个步骤都是面对接口编程,能够随意新增或修改其中的某一步,扩展性很是强,这虽然让架构变的更加复杂,但这点代价是值得的。以这个架构来讲,只要Android不死,Glide都能一直用下去。
最后,本文只是简单的给你们一个Glide的大体流程,每一个流程是怎么回事,让你们有个概念,甚至连最复杂的缓存都没提到,更不用说每一步的具体流程了,针对这些,我将会继续写一系列的文章,但愿能将Glide说清楚。