前面介绍了一级缓存,现在看二级缓存,需要request sumbit请求带入。
你可能不熟悉界面代码,需要看Fresco SimpleDraweeView界面源码分析
@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
if(null == mDatas || mDatas.size() == position)
return;
EarnItemHolder itemHolder = (EarnItemHolder) holder;
TapJoyBean tapJoyBean = mDatas.get(position);
Uri uri = Uri.parse(tapJoyBean.IconURL);
itemHolder.imageView.setImageURI(uri);
itemHolder.textView.setText(tapJoyBean.Name);
}
简单一个列子带入,SimpleDraweeView.setImageURI(uri)开始
/**
* Displays an image given by the uri.
*
* @param uri uri of the image
* @param callerContext caller context
*/
public void setImageURI(Uri uri, @Nullable Object callerContext) {
DraweeController controller = mSimpleDraweeControllerBuilder
.setCallerContext(callerContext)
.setUri(uri)
.setOldController(getController())
.build();
setController(controller);
}
设置完DraweeHolder和DraweeController绑定后,DraweeHolder开始介绍界面事件,当view:onAttach()开始submit
/**
* Callback used to notify about top-level-drawable's visibility changes.
*/
@Override
public void onVisibilityChange(boolean isVisible) {
if (mIsVisible == isVisible) {
return;
}
mEventTracker.recordEvent(isVisible ? Event.ON_DRAWABLE_SHOW : Event.ON_DRAWABLE_HIDE);
mIsVisible = isVisible;
attachOrDetachController();
}
@Override
public void onAttach() {
if (FLog.isLoggable(FLog.VERBOSE)) {
FLog.v(
TAG,
"controller %x %s: onAttach: %s",
System.identityHashCode(this),
mId,
mIsRequestSubmitted ? "request already submitted" : "request needs submit");
}
mEventTracker.recordEvent(Event.ON_ATTACH_CONTROLLER);
Preconditions.checkNotNull(mSettableDraweeHierarchy);
mDeferredReleaser.cancelDeferredRelease(this);
mIsAttached = true;
if (!mIsRequestSubmitted) {
submitRequest();
}
}
protected void submitRequest() {
final T closeableImage = getCachedImage(); // 1
if (closeableImage != null) {
mDataSource = null;
mIsRequestSubmitted = true;
mHasFetchFailed = false;
mEventTracker.recordEvent(Event.ON_SUBMIT_CACHE_HIT);
getControllerListener().onSubmit(mId, mCallerContext);
onNewResultInternal(mId, mDataSource, closeableImage, 1.0f, true, true);
return;
}
mEventTracker.recordEvent(Event.ON_DATASOURCE_SUBMIT);
getControllerListener().onSubmit(mId, mCallerContext);
mSettableDraweeHierarchy.setProgress(0, true);
mIsRequestSubmitted = true;
mHasFetchFailed = false;
mDataSource = getDataSource(); // 2
if (FLog.isLoggable(FLog.VERBOSE)) {
FLog.v(
TAG,
"controller %x %s: submitRequest: dataSource: %x",
System.identityHashCode(this),
mId,
System.identityHashCode(mDataSource));
}
final String id = mId;
final boolean wasImmediate = mDataSource.hasResult();
final DataSubscriber<T> dataSubscriber =
new BaseDataSubscriber<T>() {
@Override
public void onNewResultImpl(DataSource<T> dataSource) {
// isFinished must be obtained before image, otherwise we might set intermediate result
// as final image.
boolean isFinished = dataSource.isFinished();
float progress = dataSource.getProgress();
T image = dataSource.getResult();
if (image != null) {
onNewResultInternal(id, dataSource, image, progress, isFinished, wasImmediate);
} else if (isFinished) {
onFailureInternal(id, dataSource, new NullPointerException(), /* isFinished */ true);
}
}
@Override
public void onFailureImpl(DataSource<T> dataSource) {
onFailureInternal(id, dataSource, dataSource.getFailureCause(), /* isFinished */ true);
}
@Override
public void onProgressUpdate(DataSource<T> dataSource) {
boolean isFinished = dataSource.isFinished();
float progress = dataSource.getProgress();
onProgressUpdateInternal(id, dataSource, progress, isFinished);
}
};
mDataSource.subscribe(dataSubscriber, mUiThreadImmediateExecutor); // 3
}
又介绍一个sumbit方法,一开始调用getCachedImage()来自子类实现类PipelineDraweeController
@Override
protected CloseableReference<CloseableImage> getCachedImage() { // 来自1
if (!getExperiment().mIsFastCheckEnabled) {
return null;
}
if (mMemoryCache == null || mCacheKey == null) {
return null;
}
// We get the CacheKey
CloseableReference<CloseableImage> closeableImage = mMemoryCache.get(mCacheKey);
if (closeableImage != null && !closeableImage.get().getQualityInfo().isOfFullQuality()) {
closeableImage.close();
return null;
}
return closeableImage;
}
@Override
protected DataSource<CloseableReference<CloseableImage>> getDataSourceForRequest( // 来自2
ImageRequest imageRequest,
Object callerContext,
boolean bitmapCacheOnly) {
if (bitmapCacheOnly) {
return mImagePipeline.fetchImageFromBitmapCache(imageRequest, callerContext);
} else {
return mImagePipeline.fetchDecodedImage(imageRequest, callerContext);
}
}
1:因为我介绍二级缓存,getExperiment()这货拿到是个新的,如果在同一个界面,没有直接onDetch()这个对象返回值是检查过的,会走下面Cahe,而这个Cahce是InstrumentedMemoryCache和前面介绍的一样,这货初始化在Frescon.init(),包含了一个CoutingMemoryCache。
2:这货从子类拿到一个datasource(model),从supplied拿到一个流程,ImagePiple就开始干活和维护
3:这货订阅在ui线程,注册到model层中,是个pair<key,value>等model层数据更新,就刷新DraweeHierarchy
继续看2,因为新建view,是无法确定这个key被一级缓存了,所以走mImagePipeline.fetchDecodedImage(imageRequest, callerContext);
/**
* Submits a request for execution and returns a DataSource representing the pending decoded
* image(s).
* <p>The returned DataSource must be closed once the client has finished with it.
* @param imageRequest the request to submit
* @return a DataSource representing the pending decoded image(s)
*/
public DataSource<CloseableReference<CloseableImage>> fetchDecodedImage(
ImageRequest imageRequest,
Object callerContext) {
try {
Producer<CloseableReference<CloseableImage>> producerSequence =
mProducerSequenceFactory.getDecodedImageProducerSequence(imageRequest); // 4
return submitFetchRequest( // 5
producerSequence,
imageRequest,
ImageRequest.RequestLevel.FULL_FETCH,
callerContext);
} catch (Exception exception) {
return DataSources.immediateFailedDataSource(exception);
}
}
/**
* Returns a sequence that can be used for a request for a decoded image.
*
* @param imageRequest the request that will be submitted
* @return the sequence that should be used to process the request
*/
public Producer<CloseableReference<CloseableImage>> getDecodedImageProducerSequence(
ImageRequest imageRequest) { // 来自4
Producer<CloseableReference<CloseableImage>> pipelineSequence =
getBasicDecodedImageSequence(imageRequest);
if (imageRequest.getPostprocessor() != null) { // 这货后处理器,这里为null,因为没有特殊定制image,有兴趣翻我第一章
return getPostprocessorSequence(pipelineSequence);
} else {
return pipelineSequence;
}
}
protected AbstractProducerToDataSourceAdapter( // 来自5
Producer<T> producer,
SettableProducerContext settableProducerContext,
RequestListener requestListener) {
mSettableProducerContext = settableProducerContext;
mRequestListener = requestListener;
mRequestListener.onRequestStart(
settableProducerContext.getImageRequest(),
mSettableProducerContext.getCallerContext(),
mSettableProducerContext.getId(),
mSettableProducerContext.isPrefetch());
producer.produceResults(createConsumer(), settableProducerContext); // 6
}
private Consumer<T> createConsumer() { // 来自6
return new BaseConsumer<T>() {
@Override
protected void onNewResultImpl(@Nullable T newResult, boolean isLast) {// 来自9的回调
AbstractProducerToDataSourceAdapter.this.onNewResultImpl(newResult, isLast); // 生成11
}
@Override
protected void onFailureImpl(Throwable throwable) {
AbstractProducerToDataSourceAdapter.this.onFailureImpl(throwable);
}
@Override
protected void onCancellationImpl() {
AbstractProducerToDataSourceAdapter.this.onCancellationImpl();
}
@Override
protected void onProgressUpdateImpl(float progress) {
AbstractProducerToDataSourceAdapter.this.setProgress(progress);
}
};
}
又回到第一章我讲的request流程了。
4:会创建很多Producer和判断磁盘Cache,还有NewWorkFetch(下载底层类)
5:其实回掉接口,和JobService安排任务
然后这个producer就到BitmapMemoryCacheProducer
@Override
public void produceResults( // 来自6
final Consumer<CloseableReference<CloseableImage>> 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();
final CacheKey cacheKey = mCacheKeyFactory.getBitmapCacheKey(imageRequest, callerContext); // 7
CloseableReference<CloseableImage> cachedReference = mMemoryCache.get(cacheKey); // 8
if (cachedReference != null) {
boolean isFinal = cachedReference.get().getQualityInfo().isOfFullQuality(); // 9
if (isFinal) {
listener.onProducerFinishWithSuccess(
requestId,
getProducerName(),
listener.requiresExtraMap(requestId) ? ImmutableMap.of(VALUE_FOUND, "true") : null);
consumer.onProgressUpdate(1f);
}
consumer.onNewResult(cachedReference, isFinal); // 10
cachedReference.close();
if (isFinal) {
return;
}
}
if (producerContext.getLowestPermittedRequestLevel().getValue() >=
ImageRequest.RequestLevel.BITMAP_MEMORY_CACHE.getValue()) {
listener.onProducerFinishWithSuccess(
requestId,
getProducerName(),
listener.requiresExtraMap(requestId) ? ImmutableMap.of(VALUE_FOUND, "false") : null);
consumer.onNewResult(null, true);
return;
}
Consumer<CloseableReference<CloseableImage>> wrappedConsumer = wrapConsumer(consumer, cacheKey);
listener.onProducerFinishWithSuccess(
requestId,
getProducerName(),
listener.requiresExtraMap(requestId) ? ImmutableMap.of(VALUE_FOUND, "false") : null);
mInputProducer.produceResults(wrappedConsumer, producerContext);
}
@Override
public CacheKey getBitmapCacheKey(ImageRequest request, Object callerContext) { // 来自7
return new BitmapMemoryCacheKey(
getCacheKeySourceUri(request.getSourceUri()).toString(),
request.getResizeOptions(),
request.getAutoRotateEnabled(),
request.getImageDecodeOptions(),
null,
null,
callerContext);
}
@Override
public CloseableReference<V> get(K key) { // 来自8
CloseableReference<V> result = mDelegate.get(key);
if (result == null) {
mTracker.onCacheMiss();
} else {
mTracker.onCacheHit();
}
return result;
}
7:会利用DefautCacheFactory根据ImageRequest创建一个key
8:就是前面的InstrumentedMemoryCache,这里因为缓存过,所以直接hit了
9:如果是下载完整的image,这个值为true
10:直接回掉回去了,后面代码是请求request安排任务了,然后做完再创建bitmapCache
public abstract class AbstractDataSource<T> implements DataSource<T> {
/**
* Subclasses should invoke this method to set the result to {@code value}.
*
* <p> This method will return {@code true} if the value was successfully set, or
* {@code false} if the data source has already been set, failed or closed.
*
* <p> If the value was successfully set and {@code isLast} is {@code true}, state of the
* data source will be set to {@link AbstractDataSource.DataSourceStatus#SUCCESS}.
*
* <p> {@link #closeResult} will be called for the previous result if the new value was
* successfully set, OR for the new result otherwise.
*
* <p> This will also notify the subscribers if the value was successfully set.
*
* <p> Do NOT call this method from a synchronized block as it invokes external code of the
* subscribers.
*
* @param value the value that was the result of the task.
* @param isLast whether or not the value is last.
* @return true if the value was successfully set.
*/
protected boolean setResult(@Nullable T value, boolean isLast) { // 来自11
boolean result = setResultInternal(value, isLast); // 12
if (result) {
notifyDataSubscribers();
}
return result;
}
private void notifyDataSubscribers() { // 来自12, 13
final boolean isFailure = hasFailed();
final boolean isCancellation = wasCancelled();
for (Pair<DataSubscriber<T>, Executor> pair : mSubscribers) {
notifyDataSubscriber(pair.first, pair.second, isFailure, isCancellation);
}
}
}
private void notifyDataSubscriber( // 15
final DataSubscriber<T> dataSubscriber,
final Executor executor,
final boolean isFailure,
final boolean isCancellation) {
executor.execute(
new Runnable() {
@Override
public void run() {
if (isFailure) {
dataSubscriber.onFailure(AbstractDataSource.this);
} else if (isCancellation) {
dataSubscriber.onCancellation(AbstractDataSource.this);
} else {
dataSubscriber.onNewResult(AbstractDataSource.this);
}
}
});
@Override
public void subscribe(final DataSubscriber<T> dataSubscriber, final Executor executor) { // 14
Preconditions.checkNotNull(dataSubscriber);
Preconditions.checkNotNull(executor);
boolean shouldNotify;
synchronized(this) {
if (mIsClosed) {
return;
}
if (mDataSourceStatus == DataSourceStatus.IN_PROGRESS) {
mSubscribers.add(Pair.create(dataSubscriber, executor));
}
shouldNotify = hasResult() || isFinished() || wasCancelled();
}
if (shouldNotify) {
notifyDataSubscriber(dataSubscriber, executor, hasFailed(), wasCancelled());
}
}
}
13:其实只有下载完成才回调那个函数,那个pai是根据状态来add的,一开始为DataSourceStatus.IN_PROGRESS,然后重新创建生产者和AbstractDataSource的时候,Cache命中了,就跳过了add过程,下载完成才有这个
14:是submit创建,都在主线程的,先要判断一堆Cache和生产者
15:是最终的回掉view了
三级缓存