上一篇主要是讲到了ImagePipelineFactory和ImagePipelineConfig里面的基本内容和配置。这篇来介绍一下ImagePipeline里面很重要的一个部分:Producer
责任链模式与Pipeline
引用《Java与模式》里面对责任链(Chain of Responsibility)模式的介绍:
责任链模式是一种对象的行为模式。在责任链模式里,很多对象由每一个对象对其下家的引用而连接起来形成一条链。请求在这个链上传递,直到链上的某一个对象决定处理此请求。发出这个请求的客户端并不知道链上的哪一个对象最终处理这个请求,这使得系统可以在不影响客户端的情况下动态地重新组织和分配责任。
我们再贴一下上一篇用过的一张图:
是不是感觉跟上面所讲的责任链模式的概念很像。我们再发出请求之后,会经由DecodedMemoryCache ->EncodedMemoryCache->DiskCache->Network,在这个过程中,一旦有一个能够找到我们想要的图片资源,就会将其返回,如果没有,则交给下一个对象去处理。如果把请求比作水,每个处理对象比作阀门,这也很像是一个管道,每个阀门判断是否要将水进行拦截,然后将处理完的结果返回。所以用pipeline来形容也是很形象的(自我感觉)。说到这里,其实这个跟OkHttp里面的interceptor有些相似之处。
这里面的每个“阀门”的实现,用的就是ImagePipeline里面的Producer,而整个管道的实现,用的就是ImagePipeline里面的ProducerSequence了。
Producer
Fresco里面定义了很多的Producer,而且在里面有些Producer也有相对应的Consumer,用于对数据进行相应的操作,例如更新内存,对图片进行裁剪,压缩等等。Producer与Producer之间有类似于嵌套的操作,Consumer与Consumer之间也有,因为一个图片被这个Consumer处理完之后,还要传给下一个Consumer进行处理。这块Producer的类有点多。就按照我们之前讲的的,MemeryCache->EncodedMemoryCache->DiskCache->网络,这个流程来讲吧,Procuder顺序就是按照下面表格的顺序从上往下来的,Consumer的顺序是从下往上。
Producer | 功能 | Consumer |
PostprocessedBitmap-MemoryCacheProducer | 在MemoryCache中查找被postprocess的数据 | 将上一个Consumer传来的result存到MemoryCache |
PostprocessProducer | 如果需要postpocess,对获取到的图片进行postprocess | 在线程池中将上一个Consumer传来的result进行postprocess处理 |
BitmapMemoryCacheGetProducer | 判断数据是否在缓存中且满足最低请求级别(继承于BitmapMemoryCacheProducer) | 无Consumer |
ThreadHandoffProducer | 将接下来的Producer的操作放在线程池中(避免在UI线程中操作) | 无Consumer |
BitmapMemoryCacheProducer | 判断数据是否在缓存中且满足最低请求级别 | 判断是否要对上一个Consumer传来的result进行存储 |
DecodeProducer | 判断在Consumer中需要采用那种类型的decoder | 对上一个Consumer传来的result进行decode |
ResizeAnd-RotateProducer | 添加自身的Consumer | 根据设置的参数判断是否需要对result进行修改 |
AddImageTransformMetaDataProducer | 添加自身的Consumer | 判断是否需要设置encoded image的源数据 |
EncodedCacheKeyMultiplexProducer | 将多个相同的请求合成到一个请求中,并将相应的Consumer存在multiplexer里的set中 | 将BaseConsumer的方法传给Multiplexer |
EncodedMemoryCacheProducer |
判断数据是否在EncodedMemoryCache中 | 根据参数决定是否要存储数据 |
DiskCacheReadProducer | 判断BufferedDiskCache中是否由相应内容,如果有就返回给Consumer | 无Consumer |
DiskCacheWriteProducer | 根据参数决定是否要添加自身的CacheWriteComsumer | 将数据写入磁盘存储中 |
WebpTranscodeProducer | 添加自身的Consumer | 如果传来的result中是WebP,进行解码 |
NetworkFetchProducer | 进行网络请求,并将结果返回 | 无Consumer |
再贴一两个代码稍微解释一下吧。
MultiplexProducer
MultiplexProducer是其他复用producer的抽象父类。在MultiplexProducer中定义了一个Multiplexer类,其中定义了一个CopyOnWriteArraySet用于存储复用该multiplexer实例的comsumer和producerContext,方便之后获取到数据之后传给对应的comsumer进行操作。
@ThreadSafe
public abstract class MultiplexProducer implements Producer {
//用map存储所有的multiplexer
@GuardedBy("this")
@VisibleForTesting final Map mMultiplexers;
private final Producer mInputProducer;
protected MultiplexProducer(Producer inputProducer) {
mInputProducer = inputProducer;
mMultiplexers = new HashMap<>();
}
@Override
public void produceResults(Consumer consumer, ProducerContext context) {
K key = getKey(context);
Multiplexer multiplexer;
boolean createdNewMultiplexer;
do {
createdNewMultiplexer = false;
synchronized (this) {
//判断map中是否有对应的multiplexer
multiplexer = getExistingMultiplexer(key);
if (multiplexer == null) {
multiplexer = createAndPutNewMultiplexer(key);
createdNewMultiplexer = true;
}
}
//将Comsumer和ProducerContext添加到muliplexer中的set中
} while (!multiplexer.addNewConsumer(consumer, context));
if (createdNewMultiplexer) {
multiplexer.startInputProducerIfHasAttachedConsumers();
}
}
...
}
BitmapMemoryCacheProducer
这个是用于判断缓存中是否有相应的数据,如果有就返回没有就把任务交给下一个Producer。对应的Comsumer会将上一个Comsumer传过来的数据存储在缓存中。
public class BitmapMemoryCacheProducer implements Producer> {
private final MemoryCache mMemoryCache;
private final CacheKeyFactory mCacheKeyFactory;
private final Producer> mInputProducer;
public BitmapMemoryCacheProducer(
MemoryCache memoryCache,
CacheKeyFactory cacheKeyFactory,
Producer> inputProducer) {
mMemoryCache = memoryCache;
mCacheKeyFactory = cacheKeyFactory;
mInputProducer = inputProducer;
}
@Override
public void produceResults(
final Consumer> consumer,
final ProducerContext producerContext) {
final ProducerListener listener = producerContext.getListener();
final String requestId = producerContext.getId();
listener.onProducerStart(requestId, getProducerName());
final ImageRequest imageRequest = producerContext.getImageRequest();
final Object callerContext = producerContext.getCallerContext();
//获取到imageRequest对应的cacheKey
final CacheKey cacheKey = mCacheKeyFactory.getBitmapCacheKey(imageRequest, callerContext);
//判断缓存中是否有对应的value(CloseableImage)
CloseableReference cachedReference = mMemoryCache.get(cacheKey);
if (cachedReference != null) {
//判断图片质量是否满足要求
boolean isFinal = cachedReference.get().getQualityInfo().isOfFullQuality();
if (isFinal) {
listener.onProducerFinishWithSuccess(
requestId,
getProducerName(),
listener.requiresExtraMap(requestId)
? ImmutableMap.of(EXTRA_CACHED_VALUE_FOUND, "true")
: null);
listener.onUltimateProducerReached(requestId, getProducerName(), true);
consumer.onProgressUpdate(1f);
}
consumer.onNewResult(cachedReference, BaseConsumer.simpleStatusForIsLast(isFinal));
cachedReference.close();
if (isFinal) {
return;
}
}
//不具有向其他缓存和网络继续请求的权限,结束操作
if (producerContext.getLowestPermittedRequestLevel().getValue() >=
ImageRequest.RequestLevel.BITMAP_MEMORY_CACHE.getValue()) {
listener.onProducerFinishWithSuccess(
requestId,
getProducerName(),
listener.requiresExtraMap(requestId)
? ImmutableMap.of(EXTRA_CACHED_VALUE_FOUND, "false")
: null);
listener.onUltimateProducerReached(requestId, getProducerName(), false);
consumer.onNewResult(null, Consumer.IS_LAST);
return;
}
//添加自己的comsumer
Consumer> wrappedConsumer = wrapConsumer(consumer, cacheKey);
listener.onProducerFinishWithSuccess(
requestId,
getProducerName(),
listener.requiresExtraMap(requestId)
? ImmutableMap.of(EXTRA_CACHED_VALUE_FOUND, "false")
: null);
//传给下一个Producer进行处理
mInputProducer.produceResults(wrappedConsumer, producerContext);
}
//添加自己的Comsumer
protected Consumer> wrapConsumer(
final Consumer> consumer,
final CacheKey cacheKey) {
//定义自己的comsumer,并重写onNewResultImpl方法
return new DelegatingConsumer<
CloseableReference,
CloseableReference>(consumer) {
@Override
public void onNewResultImpl(
CloseableReference newResult,
@Status int status) {
final boolean isLast = isLast(status);
// 如果上一个comsumer传来的result为空,不处理
if (newResult == null) {
if (isLast) {
getConsumer().onNewResult(null, status);
}
return;
}
// 只是部分结果,不处理
if (newResult.get().isStateful() || statusHasFlag(status, IS_PARTIAL_RESULT)) {
getConsumer().onNewResult(newResult, status);
return;
}
if (!isLast) {
CloseableReference currentCachedResult = mMemoryCache.get(cacheKey);
//如果缓存中已有对应图片
if (currentCachedResult != null) {
try {
QualityInfo newInfo = newResult.get().getQualityInfo();
QualityInfo cachedInfo = currentCachedResult.get().getQualityInfo();
//如果缓存中的图片的quality不差于上一个comsumer传来的图片
//返回缓存中的图片
if (cachedInfo.isOfFullQuality() || cachedInfo.getQuality() >= newInfo.getQuality()) {
getConsumer().onNewResult(currentCachedResult, status);
return;
}
} finally {
CloseableReference.closeSafely(currentCachedResult);
}
}
}
// 将图片存到缓存中,并传给下一个comsumer
CloseableReference newCachedResult =
mMemoryCache.cache(cacheKey, newResult);
try {
if (isLast) {
getConsumer().onProgressUpdate(1f);
}
getConsumer().onNewResult(
(newCachedResult != null) ? newCachedResult : newResult, status);
} finally {
CloseableReference.closeSafely(newCachedResult);
}
}
};
}
protected String getProducerName() {
return PRODUCER_NAME;
}
}
好了Producer这块就先到这里了...接下来看一下ProducerSequence。
ProducerSequence
上面说了,ProducerSequence就是整个管道的具体实现,具体的方法都在ProducerSequenceFactory中。那我们来看下是怎么实现的,同样也是看,MemeryCache->EncodedMemoryCache->DiskCache->网络,这一个流程吧。
在ImagePipeline中会调用getDecodedImageProducerSequence方法:
public Producer> getDecodedImageProducerSequence(
ImageRequest imageRequest) {
//获得一个producer sequence
Producer> pipelineSequence =
getBasicDecodedImageSequence(imageRequest);
//在Sequence前面添加了PostprocessorProducer
if (imageRequest.getPostprocessor() != null) {
pipelineSequence = getPostprocessorSequence(pipelineSequence);
}
//在Sequence前面添加了BitmapPrepareProducer
if (mUseBitmapPrepareToDraw) {
pipelineSequence = getBitmapPrepareSequence(pipelineSequence);
}
return pipelineSequence;
}
首先这个的sequence只是一个抽象概念,实际上就是用一个个的producer相互嵌套来进行实现。有点像装饰模式的感觉。
再看一下getBasicDecodedImageSequence方法:
private Producer> getBasicDecodedImageSequence(
ImageRequest imageRequest) {
Preconditions.checkNotNull(imageRequest);
Uri uri = imageRequest.getSourceUri();
Preconditions.checkNotNull(uri, "Uri is null.");
switch (imageRequest.getSourceUriType()) {
//网络获取
case SOURCE_TYPE_NETWORK:
return getNetworkFetchSequence();
case SOURCE_TYPE_LOCAL_VIDEO_FILE:
return getLocalVideoFileFetchSequence();
case SOURCE_TYPE_LOCAL_IMAGE_FILE:
return getLocalImageFileFetchSequence();
case SOURCE_TYPE_LOCAL_CONTENT:
if (MediaUtils.isVideo(mContentResolver.getType(uri))) {
return getLocalVideoFileFetchSequence();
}
return getLocalContentUriFetchSequence();
case SOURCE_TYPE_LOCAL_ASSET:
return getLocalAssetFetchSequence();
case SOURCE_TYPE_LOCAL_RESOURCE:
return getLocalResourceFetchSequence();
case SOURCE_TYPE_QUALIFIED_RESOURCE:
return getQualifiedResourceFetchSequence();
case SOURCE_TYPE_DATA:
return getDataFetchSequence();
default:
throw new IllegalArgumentException(
"Unsupported uri scheme! Uri is: " + getShortenedUriString(uri));
}
}
这个方法就是根据我们发出的图像请求的uri来决定我们要采用哪一个sequence(例如从网络获取的sequence,从本地文件获取的sequence),因为是要从网络获取的,看一下getNetworkFetchSequence():
private synchronized Producer> getNetworkFetchSequence() {
if (mNetworkFetchSequence == null) {
mNetworkFetchSequence =
newBitmapCacheGetToDecodeSequence(getCommonNetworkFetchToEncodedMemorySequence());
}
return mNetworkFetchSequence;
}
这里是调用到了两个方法,newBitmapCacheGetToDecodeSequence()和getCommonNetworkFetchToEncodedMemory-Sequence()。先看一下第一个方法:
private Producer> newBitmapCacheGetToDecodeSequence(
Producer inputProducer) {
//生成DecodeProducer实例
DecodeProducer decodeProducer = mProducerFactory.newDecodeProducer(inputProducer);
//用该方法封装
return newBitmapCacheGetToBitmapCacheSequence(decodeProducer);
}
这里生成了一个DecodeProducer实例,并将其传到newBitmapCacheGetToBitmapCacheSequence()中。看一下代码:
private Producer> newBitmapCacheGetToBitmapCacheSequence(
Producer> inputProducer) {
//生成BitmapMemoryCacheProducer实例,并将DecodeProducer传入
BitmapMemoryCacheProducer bitmapMemoryCacheProducer =
mProducerFactory.newBitmapMemoryCacheProducer(inputProducer);
//生成BitmapMemoryCacheKeyMultiplexProducer实例并将BitmapMemoryCacheProducer传入
BitmapMemoryCacheKeyMultiplexProducer bitmapKeyMultiplexProducer =
mProducerFactory.newBitmapMemoryCacheKeyMultiplexProducer(bitmapMemoryCacheProducer);
//生成BackgroundThreadHandoffProducer实例并将BitmapMemoryCacheKeyMultiplexProducer传入
ThreadHandoffProducer> threadHandoffProducer =
mProducerFactory.newBackgroundThreadHandoffProducer(
bitmapKeyMultiplexProducer,
mThreadHandoffProducerQueue);
//生成BitmapMemoryCacheGetProducer实例并将BackgroundThreadHandoffProducer传入,将BitmapMemoryCacheGetProducer返回
return mProducerFactory.newBitmapMemoryCacheGetProducer(threadHandoffProducer);
}
从这个方法就可以比较明显的看到整个Pipeline是怎么形成的了,其实就是不断的生成Producer实例,并将下一个Producer实例传入到上一个中。而在Producer的代码中也能看到,当前Producer在执行失败之后,会让它所组合的另一个Producer实例进行下一步的操作。所以整个管道的实现就是这么来的。getCommonNetworkFetchToEncodedMemorySequence()方法就不看了,也是一样的操作。
到这里应该算Pipeline这块的底层实现都大致讲了一下。接下来还有一个问题,就是我们是在哪调用到Pipeline里面的方法的,因为我们正常发请求就是设置下uri或者设置下controller,就能够实现图像请求了。还有就是我们怎么直接获取到Pipeline实例进行一些直接对Pipeline进行操作。这一块就等下一篇再来讲吧。