前面介紹了一級(jí)緩存旗唁,現(xiàn)在看二級(jí)緩存仑嗅,需要request sumbit請(qǐng)求帶入宴倍。
你可能不熟悉界面代碼,需要看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);
}
簡(jiǎn)單一個(gè)列子帶入仓技,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);
}
設(shè)置完DraweeHolder和DraweeController綁定后鸵贬,DraweeHolder開始介紹界面事件,當(dāng)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
}
又介紹一個(gè)sumbit方法脖捻,一開始調(diào)用getCachedImage()來自子類實(shí)現(xiàn)類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:因?yàn)槲医榻B二級(jí)緩存阔逼,getExperiment()這貨拿到是個(gè)新的,如果在同一個(gè)界面地沮,沒有直接onDetch()這個(gè)對(duì)象返回值是檢查過的嗜浮,會(huì)走下面Cahe,而這個(gè)Cahce是InstrumentedMemoryCache和前面介紹的一樣摩疑,這貨初始化在Frescon.init()危融,包含了一個(gè)CoutingMemoryCache。
2:這貨從子類拿到一個(gè)datasource(model)雷袋,從supplied拿到一個(gè)流程吉殃,ImagePiple就開始干活和維護(hù)
3:這貨訂閱在ui線程,注冊(cè)到model層中楷怒,是個(gè)pair<key,value>等model層數(shù)據(jù)更新蛋勺,就刷新DraweeHierarchy
繼續(xù)看2,因?yàn)樾陆╲iew率寡,是無法確定這個(gè)key被一級(jí)緩存了迫卢,所以走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冶共,因?yàn)闆]有特殊定制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的回調(diào)
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:會(huì)創(chuàng)建很多Producer和判斷磁盤Cache,還有NewWorkFetch(下載底層類)
5:其實(shí)回掉接口家卖,和JobService安排任務(wù)
然后這個(gè)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:會(huì)利用DefautCacheFactory根據(jù)ImageRequest創(chuàng)建一個(gè)key
8:就是前面的InstrumentedMemoryCache眨层,這里因?yàn)榫彺孢^,所以直接hit了
9:如果是下載完整的image上荡,這個(gè)值為true
10:直接回掉回去了趴樱,后面代碼是請(qǐng)求request安排任務(wù)了,然后做完再創(chuàng)建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:其實(shí)只有下載完成才回調(diào)那個(gè)函數(shù)叁征,那個(gè)pai是根據(jù)狀態(tài)來add的,一開始為DataSourceStatus.IN_PROGRESS逛薇,然后重新創(chuàng)建生產(chǎn)者和AbstractDataSource的時(shí)候捺疼,Cache命中了,就跳過了add過程永罚,下載完成才有這個(gè)
14:是submit創(chuàng)建啤呼,都在主線程的,先要判斷一堆Cache和生產(chǎn)者
15:是最終的回掉view了
三級(jí)緩存