之前有大概的了解fresco
,也看过部分源代码,现在项目中使用的越来越多,觉得有必要整理一下。这篇博客主要是分析了fresco
整体的框架。没有看过准备去看fresco
源代码的童鞋可以看看这篇博客进行参考一下。基于fresco 1.5.0
怎么使用
1.在Application
中对fresco
初始化。主要是配置所有的Drawee的公共样式。请求和配置(磁盘缓存、内存缓存等的大小路径)。下面一个简单的例子。
|
|
2.使用SimpleDraweeView
。主要是配置图片的路径,展示的样式(圆角、默认图、失败图、重试图等等)。下面是一个简单例子。
|
|
整体的module 层次
Drawee
:控制展示,比如View
加载到屏幕以后才去请求图片。控制默认图、错误图等的展示。
ImagePiple
:处理不同来源图片的加载(网络、sd 卡等等)。
逻辑实现的框架:Producer、Consumer
fresco
实现了很多的逻辑:从网络获取图片、从磁盘获取图片、缓存在磁盘、解码(解析gif)等等。如何将这些操作解耦是一个值得好好考虑的问题。这么多不同需求的组合,最开始想到是使用责任链模式,将每一小块单独出来,处理完以后给另外的一个小块。这样就相当于对每一个请求只是需要构造一个合适的”链子”就好了。
看一个网络请求完整的”链子”:
NetworkFetchProducer<- // 网络获取图片
WebpTranscodeProducer<- // webp 转化
DiskCacheWriteProducer(PartialDiskCacheProducer)<- // Partial逻辑(缓存已经下载的部分)
MediaVariationsFallbackProducer<- // 当不存在时,则会在相同的文件中选择最合适的展示
DiskCacheReadProducer<- // 读取磁盘缓存的内容。smallImageBufferedDiskCache 是为了快速命中吧
EncodedMemoryCacheProducer<- // 获取到了数据但是没有展示出来(没有解码)的情况
EncodedCacheKeyMultiplexProducer<-
AddImageTransformMetaDataProducer<- // 获取到相应的head meta
ResizeAndRotateProducer-> // 会对图片优化
DecodeProducer->
BitmapMemoryCacheProducer-> // 包含了cache的操作
BitmapMemoryCacheKeyMultiplexProducer-> // 从缓存读取的时候也是有优化的
ThreadHandoffProducer-> // 为任务分配线程
BitmapMemoryCacheGetProducer->
(PostprocessorProducer->PostprocessedBitmapMemoryCacheProducer)-> // 后处理bitmap,对Bitmap 的处理
(BitmapPrepareProducer) // 用来Andorid N 以后的优化
下面是所实现的所有Procuder
,逻辑还是挺多挺复杂的,但是分成一个个看相应的逻辑还是很清晰的。
这里面有一个比较特殊的Producer
是MultiplexProducer
,用来将多个请求合并成一个请求。举一个例子,在某一段时间里面很有可能会去请求一张图片很多次,这样可能会导致创建多条”链子”,都需要网络请求,但是实际上只需要请求一次以后分别处理就好。怎么实现的呢,MultiplexProducer
中有一个成员变量Map<K, Multiplexer> mMultiplexers
用来保存每一个请求对应的Multiplexer
(用来管理多个Consumer
),Multiplexer
里面的成员变量CopyOnWriteArraySet<Pair<Consumer<T>, ProducerContext>>
代表的是该请求对应的所有的Consumer
,当请求处理完成以后分别去处理集合里面的Consumer
。
还有一点很重要的是当相同的请求过来时是不会通知下面的Producer
继续执行的。
|
|
Drawable 框架
fresco
展示图片的逻辑也考虑的很充分,包括默认图、错误图、重试图、加载图、调试图片以及最终展示的图片。下面是fresco
实现的Drawable
,很明显的装饰模式。
每次更新(设置Image、失败)的时候都需要更新View
(1).RootDrawable
(2).RoundedCornersDrawable
(3).FadeDrawable
(4).Drawable[]:代表的是一组Drawable
ScaleTypeDrawable:background
ScaleTypeDrawable:placeholer
ScaleTypeDrawable:actual image
:progress bar
:retry
:failure
上面是最终展示在SimpleDraweeView
中的Drawable
,当请求开始、请求中、请求结束的动作执行的时候只需要分别处理相应的Drawble
(比如请求成功展示最终的图片)就好。
一个总结
fresco
很强大,基本上能够完成图片加载的所有功能,特别适合含有特别多图片的应用。对内存也做了相应的优化。从UIL
切换到fresco
感觉工作量不是很大,现在如果从fresco
切换到其它框架可能实现不了了,真担心被这个框架被绑架了😅。