Fresco浅析
SimpleDraweeView
层级初始化
GenericDraweeHierarchyInflater
从xml中解析SimpleDraweeView
属性值,(收集属性),然后赋值给GenericDraweeHierarchyBuilder
去创建,在GenericDraweeView
的构造函数中去build,创建GenericDraweeHierarchy
,也就是初始化XML中的属性。这个和代码创建一个效果。类似placeholderImage这些是按照层级放到Drawable[]中,根据这个创建mTopLevelDrawable
,mTopLevelDrawable
中可以做渐变,进度等操作。就是改变Drawable[]中不同的drawable实现的。然后setController时候会设置mTopLevelDrawable
先显示。
判断OldController
能不能复用是根据DraweeHolder::isControllerValid
判断,实际上是mController.getHierarchy() == mHierarchy
PipelineDraweeController
是唯一实现的
内存缓存
内存缓存包括已经解码(BitmapMemoryCache
)的和未解码的(EncodedMemoryCache
)。在源码中表示为MemoryCache
,有两个实现类,InstrumentedMemoryCache
可以做一些自定义的东西,CountingMemoryCache
主要缓存类。缓存的节点是Entry
,里面有
|
|
使用CountingLruMap
来存放数据,其中起作用的是LinkedHashMap<K, V> mMap
。很显然是LRU。
文件缓存
会有CONTENT_FILE_EXTENSION = ".cnt";
的缓存文件和TEMP_FILE_EXTENSION = ".tmp";
临时缓存文件。文件储存主要是DefaultDiskStorage
起作用。DiskStorageCache
是实现文件缓存的主要类,在maybeEvictFilesInCacheDir
也实现了LRU控制缓存。上面还有一层是BufferedDiskCache
中的StagingArea mStagingArea
,查找的现在这里面查找,找不到通过getAsync
从DiskStorageCache
中查找。写入的时候会先创建临时文件,然后在endInsert
中使用commit
完成缓存文件替换,写入。
Pipeline流水线
触发加载图片请求是在进入到AbstractDraweeController
的onAttach
,然后 submitRequest();
请求图片操作。先去getCachedImage()
获取缓存解码图片,根据mCacheKey
从mMemoryCache中
获取,mCacheKey
中包含url和对图片的一些设置,例如resize
,rotation
等,都是从imagerequest
中获取的。mMemoryCache
是通过mImagePipeline.getBitmapMemoryCache()
获得,是通过BitmapCountingMemoryCacheFactory创建的CountingMemoryCache
,
获取到CloseableReference<CloseableImage>
,然后包装成drawable
,通过GenericDraweeHierarchy
设置给mActualImageWrapper
,这个也存在之前的drawable数组中,也就是ACTUAL_IMAGE
。
层层Producer
处理,责任链,每一层存在本层能否直接给Consumer
提供数据,不能则将Consumer
在本层包装一下交给下一层去获取数据。本层的Consumer
做一些缓存数据等操作。
例如BitmapMemoryCacheProducer
和DecodeProducer
就是上下层的关系。首先先在BitmapMemoryCacheProducer
的
produceResults(
final Consumer<CloseableReference<CloseableImage>> consumer,
final ProducerContext producerContext)
方法中寻找解码的图片,如果有,返回给消费解码数据的consumer
,如果没有则用本层的wrapConsumer
包装一下消费解码图片的消费者传递给下面一层的DecodeProducer
,调用DecodeProducer
的produceResults
方法。同理,DecodeProduce
r本身不产生数据,他只处理图片的解码,所有把上层传来的consumer
再包装一次,传给下面的生产者。例如在磁盘上找到了符合条件的图片,则会走消费这一条路,调用层层的consumer
,例如到了DecodeProducer
的consumer
,会异步去解码,解码成功后再去调用上层的Consumer
的onNewResult
,内部会调用对应层的onNewResultImpl
方法,例如BitmapMemoryCacheProducer
中的wrapConsumer
的DelegatingConsumer
的onNewResultImpl
,这里会在内存中缓存解码的图片了。然后再调用上层的consumer
。最上层的Consumer
是在AbstractProducerToDataSourceAdapter
中createConsumer
创建的。然后通过它的setResult
方法通知所有的dataSubscriber
,然后在主线程回调dataSubscriber.onNewResult
,然后就是使用 mSettableDraweeHierarchy.setImage
去给mActualImageWrapper.setDrawable(drawable);
这就完成了图片的显示。
整个的producer的顺序是在ProducerSequenceFactory::getDecodedImageProducerSequence
的方法里面确立的。