前言
Fresco 中設(shè)計有一個叫做 image pipeline 的模塊余爆。它負(fù)責(zé)從網(wǎng)絡(luò)斋配,從本地文件系統(tǒng),本地資源加載圖片寄悯。為了最大限度節(jié)省空間和CPU時間萤衰,它含有3級緩存設(shè)計(2級內(nèi)存,1級文件)猜旬。
Fresco 中設(shè)計有一個叫做 Drawees 模塊脆栋,方便地顯示loading圖,當(dāng)圖片不再顯示在屏幕上時洒擦,及時地釋放內(nèi)存和空間占用椿争。
使用
Fresco使用:
首先需要在layout布局上使用fresco的simpleDraweeView:
<com.facebook.drawee.view.SimpleDraweeView
android:id="@+id/simpleDraweeView"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
然后再java代碼中使用:
SimpleDraweeView simpleDraweeView = findViewById(R.id.simpleDraweeView);
Uri uri = Uri.parse("https://www.baidu.com/img/xinshouye_034fec51df225fe8410f36ad3f2fccf6.png");
simpleDraweeView.setImageURI(uri);
由上述使用方法可以看出,只需要給定一個容器然后傳入一個url地址熟嫩,即可完成對圖片的加載丘薛;那么它的內(nèi)部運行流程是什么樣的呢?
fresco整個業(yè)務(wù)流程:
E:\我的圖片\20160523111021635.png
入口
很明顯邦危,SimpleDraweeView是我們先要弄清楚的,首先要明白它是繼承自ImageView的,并且具有l(wèi)ayout布局洋侨,顯然是自定義View,第一步必然是從布局文件樣式中讀取屬性值。
那么我們直接看看simpleDraweeView.setImageURI(uri)方法:
public void setImageURI(Uri uri, @Nullable Object callerContext) {
DraweeController controller = mSimpleDraweeControllerBuilder
.setCallerContext(callerContext)
.setUri(uri)
.setOldController(getController())
.build();
setController(controller);
}
首先它創(chuàng)建了一個Controller并調(diào)用setController倦蚪,看一下Controller是怎么創(chuàng)建的:
@Override
public AbstractDraweeController build() {
validate();
//賦值圖片請求
// if only a low-res request is specified, treat it as a final request.
if (mImageRequest == null && mMultiImageRequests == null && mLowResImageRequest != null) {
mImageRequest = mLowResImageRequest;
mLowResImageRequest = null;
}
//創(chuàng)建ontroller
return buildController();
}
protected AbstractDraweeController buildController() {
AbstractDraweeController controller = obtainController();//獲取請求
controller.setRetainImageOnFailure(getRetainImageOnFailure());
controller.setContentDescription(getContentDescription());
controller.setControllerViewportVisibilityListener(getControllerViewportVisibilityListener());
maybeBuildAndSetRetryManager(controller);
maybeAttachListeners(controller);
return controller;
}
@Override
protected PipelineDraweeController obtainController() {
DraweeController oldController = getOldController();
PipelineDraweeController controller;
if (oldController instanceof PipelineDraweeController) {
controller = (PipelineDraweeController) oldController;
controller.initialize(
obtainDataSourceSupplier(),
generateUniqueControllerId(),
getCacheKey(),
getCallerContext(),
mCustomDrawableFactories);
} else {
//工廠模式創(chuàng)建Controller
controller = mPipelineDraweeControllerFactory.newController(
obtainDataSourceSupplier(),
generateUniqueControllerId(),
getCacheKey(),
getCallerContext(),
mCustomDrawableFactories);
}
return controller;
}
public PipelineDraweeController newController(
Supplier<DataSource<CloseableReference<CloseableImage>>> dataSourceSupplier,
String id,
CacheKey cacheKey,
Object callerContext,
@Nullable ImmutableList<DrawableFactory> customDrawableFactories) {
Preconditions.checkState(mResources != null, "init() not called");
// Field values passed as arguments so that any subclass of PipelineDraweeControllerFactory
// can simply override internalCreateController() and return a custom Drawee controller
//創(chuàng)建Controller
PipelineDraweeController controller = internalCreateController(
mResources,
mDeferredReleaser,
mAnimatedDrawableFactory,
mUiThreadExecutor,
mMemoryCache,
mDrawableFactories,
customDrawableFactories,
dataSourceSupplier,
id,
cacheKey,
callerContext);
if (mDebugOverlayEnabledSupplier != null) {
controller.setDrawDebugOverlay(mDebugOverlayEnabledSupplier.get());
}
return controller;
}
protected PipelineDraweeController internalCreateController(
Resources resources,
DeferredReleaser deferredReleaser,
DrawableFactory animatedDrawableFactory,
Executor uiThreadExecutor,
MemoryCache<CacheKey, CloseableImage> memoryCache,
@Nullable ImmutableList<DrawableFactory> globalDrawableFactories,
@Nullable ImmutableList<DrawableFactory> customDrawableFactories,
Supplier<DataSource<CloseableReference<CloseableImage>>> dataSourceSupplier,
String id,
CacheKey cacheKey,
Object callerContext) {
//至此Controller創(chuàng)建完畢 為PipelineDraweeController實例
PipelineDraweeController controller = new PipelineDraweeController(
resources,
deferredReleaser,
animatedDrawableFactory,
uiThreadExecutor,
memoryCache,
dataSourceSupplier,
id,
cacheKey,
callerContext,
globalDrawableFactories);
controller.setCustomDrawableFactories(customDrawableFactories);
return controller;
}
接下來希坚,讓我們看一看setController方法:
/** Sets the controller. */
public void setController(@Nullable DraweeController draweeController) {
mDraweeHolder.setController(draweeController);
super.setImageDrawable(mDraweeHolder.getTopLevelDrawable());
}
繼續(xù)追蹤mDraweeHolder.setController(draweeController):
public void setController(@Nullable DraweeController draweeController) {
boolean wasAttached = mIsControllerAttached;
if (wasAttached) {
detachController();
}
// Clear the old controller
if (isControllerValid()) {
mEventTracker.recordEvent(Event.ON_CLEAR_OLD_CONTROLLER);
mController.setHierarchy(null);
}
mController = draweeController;
if (mController != null) {
mEventTracker.recordEvent(Event.ON_SET_CONTROLLER);
mController.setHierarchy(mHierarchy);
} else {
mEventTracker.recordEvent(Event.ON_CLEAR_CONTROLLER);
}
if (wasAttached) {
attachController();
}
}
將draweeController賦值給mController,然后調(diào)用attachController方法:
private void attachController() {
if (mIsControllerAttached) {
return;
}
mEventTracker.recordEvent(Event.ON_ATTACH_CONTROLLER);
mIsControllerAttached = true;
if (mController != null &&
mController.getHierarchy() != null) {
mController.onAttach();
}
}
繼續(xù)追蹤onAttach方法:
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();//提交數(shù)據(jù)請求
}
}
終于看到提交數(shù)據(jù)請求了:
protected void submitRequest() {
//獲取內(nèi)存緩存
final T closeableImage = getCachedImage();
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;
//獲取數(shù)據(jù)~~~
mDataSource = getDataSource();
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();
//觀察者訂閱數(shù)據(jù)請求
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);
}
可以看到數(shù)據(jù)請求邏輯在getDataSource里面:
@Override
protected DataSource<CloseableReference<CloseableImage>> getDataSource() {
if (FLog.isLoggable(FLog.VERBOSE)) {
FLog.v(TAG, "controller %x: getDataSource", System.identityHashCode(this));
}
return mDataSourceSupplier.get();
}
最終getDataSource將數(shù)據(jù)請求交給了mDataSourceSupplier.get(),那么mDataSourceSupplier是何方神圣呢陵且?mDataSourceSupplier是什么時候初始化的呢裁僧?
@Override
protected PipelineDraweeController obtainController() {
DraweeController oldController = getOldController();
PipelineDraweeController controller;
if (oldController instanceof PipelineDraweeController) {
controller = (PipelineDraweeController) oldController;
controller.initialize(
obtainDataSourceSupplier(),
generateUniqueControllerId(),
getCacheKey(),
getCallerContext(),
mCustomDrawableFactories);
} else {
controller = mPipelineDraweeControllerFactory.newController(
obtainDataSourceSupplier(),
generateUniqueControllerId(),
getCacheKey(),
getCallerContext(),
mCustomDrawableFactories);
}
return controller;
}
我們發(fā)現(xiàn),在創(chuàng)建controller的時候會傳遞obtainDataSourceSupplier方法為參數(shù):
protected Supplier<DataSource<IMAGE>> obtainDataSourceSupplier() {
if (mDataSourceSupplier != null) {
return mDataSourceSupplier;
}
Supplier<DataSource<IMAGE>> supplier = null;
// final image supplier;
if (mImageRequest != null) {
//獲取網(wǎng)絡(luò)數(shù)據(jù)提供者
supplier = getDataSourceSupplierForRequest(mImageRequest);
} else if (mMultiImageRequests != null) {
supplier = getFirstAvailableDataSourceSupplier(mMultiImageRequests, mTryCacheOnlyFirst);
}
// increasing-quality supplier; highest-quality supplier goes first
if (supplier != null && mLowResImageRequest != null) {
List<Supplier<DataSource<IMAGE>>> suppliers = new ArrayList<>(2);
suppliers.add(supplier);
suppliers.add(getDataSourceSupplierForRequest(mLowResImageRequest));
supplier = IncreasingQualityDataSourceSupplier.create(suppliers);
}
// no image requests; use null data source supplier
if (supplier == null) {
supplier = DataSources.getFailedDataSourceSupplier(NO_REQUEST_EXCEPTION);
}
return supplier;
}
/** Creates a data source supplier for the given image request. */
protected Supplier<DataSource<IMAGE>> getDataSourceSupplierForRequest(
final REQUEST imageRequest,
final CacheLevel cacheLevel) {
final Object callerContext = getCallerContext();
return new Supplier<DataSource<IMAGE>>() {
@Override
public DataSource<IMAGE> get() {
return getDataSourceForRequest(imageRequest, callerContext, cacheLevel);
}
@Override
public String toString() {
return Objects.toStringHelper(this)
.add("request", imageRequest.toString())
.toString();
}
};
}
至此mDataSourceSupplier才浮出水面慕购,最后實現(xiàn)了get方法正是獲取圖片數(shù)據(jù)請求的方法:
@Override
protected DataSource<CloseableReference<CloseableImage>> getDataSourceForRequest(
ImageRequest imageRequest,
Object callerContext,
CacheLevel cacheLevel) {
return mImagePipeline.fetchDecodedImage(
imageRequest,
callerContext,
convertCacheLevelToRequestLevel(cacheLevel));
}
繼續(xù)追蹤:
public DataSource<CloseableReference<CloseableImage>> fetchDecodedImage(
ImageRequest imageRequest,
Object callerContext,
ImageRequest.RequestLevel lowestPermittedRequestLevelOnSubmit) {
try {
Producer<CloseableReference<CloseableImage>> producerSequence =
mProducerSequenceFactory.getDecodedImageProducerSequence(imageRequest);
return submitFetchRequest(
producerSequence,
imageRequest,
lowestPermittedRequestLevelOnSubmit,
callerContext);
} catch (Exception exception) {
return DataSources.immediateFailedDataSource(exception);
}
}
繼續(xù)追蹤submitFetchRequest:
private <T> DataSource<CloseableReference<T>> submitFetchRequest(
Producer<CloseableReference<T>> producerSequence,
ImageRequest imageRequest,
ImageRequest.RequestLevel lowestPermittedRequestLevelOnSubmit,
Object callerContext) {
final RequestListener requestListener = getRequestListenerForRequest(imageRequest);
try {
ImageRequest.RequestLevel lowestPermittedRequestLevel =
ImageRequest.RequestLevel.getMax(
imageRequest.getLowestPermittedRequestLevel(),
lowestPermittedRequestLevelOnSubmit);
SettableProducerContext settableProducerContext = new SettableProducerContext(
imageRequest,
generateUniqueFutureId(),
requestListener,
callerContext,
lowestPermittedRequestLevel,
/* isPrefetch */ false,
imageRequest.getProgressiveRenderingEnabled() ||
imageRequest.getMediaVariations() != null ||
!UriUtil.isNetworkUri(imageRequest.getSourceUri()),
imageRequest.getPriority());
return CloseableProducerToDataSourceAdapter.create(
producerSequence,
settableProducerContext,
requestListener);
} catch (Exception exception) {
return DataSources.immediateFailedDataSource(exception);
}
}
繼續(xù)追蹤CloseableProducerToDataSourceAdapter.create
public static <T> DataSource<T> create(
Producer<T> producer,
SettableProducerContext settableProducerContext,
RequestListener listener) {
return new ProducerToDataSourceAdapter<T>(
producer,
settableProducerContext,
listener);
}
繼續(xù)
protected AbstractProducerToDataSourceAdapter(
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);
}
重點在producer.produceResults聊疲,但producer是什么呢?
public Producer<CloseableReference<PooledByteBuffer>>
getNetworkFetchEncodedImageProducerSequence() {
synchronized (this) {
if (mNetworkEncodedImageProducerSequence == null) {
mNetworkEncodedImageProducerSequence = new RemoveImageTransformMetaDataProducer(
getBackgroundNetworkFetchToEncodedMemorySequence());
}
}
return mNetworkEncodedImageProducerSequence;
}
一直追蹤沪悲,發(fā)現(xiàn)具體請求網(wǎng)絡(luò)數(shù)據(jù)在NetworkFetchProducer這個類,其中有一個mNetworkFetcher.fetch方法:
@Override
public void produceResults(Consumer<EncodedImage> consumer, ProducerContext context) {
context.getListener()
.onProducerStart(context.getId(), PRODUCER_NAME);
final FetchState fetchState = mNetworkFetcher.createFetchState(consumer, context);
mNetworkFetcher.fetch(
fetchState, new NetworkFetcher.Callback() {
@Override
public void onResponse(InputStream response, int responseLength) throws IOException {
NetworkFetchProducer.this.onResponse(fetchState, response, responseLength);
}
@Override
public void onFailure(Throwable throwable) {
NetworkFetchProducer.this.onFailure(fetchState, throwable);
}
@Override
public void onCancellation() {
NetworkFetchProducer.this.onCancellation(fetchState);
}
});
}
看一下mNetworkFetcher.createFetchState方法做什么工作:
我們發(fā)現(xiàn)获洲,有兩個類實現(xiàn)了這個接口,分別是HttpUrlConnectionNetworkFetcher和OkHttpNetworkFetcher,走到這一步就很明顯了:Fresco加載圖片用的是okhttp和httpurlconnection。
讓我們看一下Fresco的okhttp加載數(shù)據(jù)實現(xiàn):
protected void fetchWithRequest(
final OkHttpNetworkFetchState fetchState,
final Callback callback,
final Request request) {
final Call call = mCallFactory.newCall(request);
fetchState.getContext().addCallbacks(
new BaseProducerContextCallbacks() {
@Override
public void onCancellationRequested() {
if (Looper.myLooper() != Looper.getMainLooper()) {
call.cancel();
} else {
mCancellationExecutor.execute(new Runnable() {
@Override public void run() {
call.cancel();
}
});
}
}
});
call.enqueue(
new okhttp3.Callback() {
@Override
public void onResponse(Call call, Response response) throws IOException {
fetchState.responseTime = SystemClock.elapsedRealtime();
final ResponseBody body = response.body();
try {
if (!response.isSuccessful()) {
handleException(
call,
new IOException("Unexpected HTTP code " + response),
callback);
return;
}
BytesRange responseRange =
BytesRange.fromContentRangeHeader(response.header("Content-Range"));
if (responseRange != null) {
fetchState.setResponseBytesRange(responseRange);
fetchState.setOnNewResultStatusFlags(Consumer.IS_PARTIAL_RESULT);
}
long contentLength = body.contentLength();
if (contentLength < 0) {
contentLength = 0;
}
callback.onResponse(body.byteStream(), (int) contentLength);
} catch (Exception e) {
handleException(call, e, callback);
} finally {
try {
body.close();
} catch (Exception e) {
FLog.w(TAG, "Exception when closing response body", e);
}
}
}
@Override
public void onFailure(Call call, IOException e) {
handleException(call, e, callback);
}
});
}
而Fresco的httpurlconnection實現(xiàn):
void fetchSync(FetchState fetchState, Callback callback) {
HttpURLConnection connection = null;
InputStream is = null;
try {
connection = downloadFrom(fetchState.getUri(), MAX_REDIRECTS);
if (connection != null) {
is = connection.getInputStream();
callback.onResponse(is, -1);
}
} catch (IOException e) {
callback.onFailure(e);
} finally {
if (is != null) {
try {
is.close();
} catch (IOException e) {
// do nothing and ignore the IOException here
}
}
if (connection != null) {
connection.disconnect();
}
}
}
private HttpURLConnection downloadFrom(Uri uri, int maxRedirects) throws IOException {
HttpURLConnection connection = openConnectionTo(uri);
int responseCode = connection.getResponseCode();
if (isHttpSuccess(responseCode)) {
return connection;
} else if (isHttpRedirect(responseCode)) {
String nextUriString = connection.getHeaderField("Location");
connection.disconnect();
Uri nextUri = (nextUriString == null) ? null : Uri.parse(nextUriString);
String originalScheme = uri.getScheme();
if (maxRedirects > 0 && nextUri != null && !nextUri.getScheme().equals(originalScheme)) {
return downloadFrom(nextUri, maxRedirects - 1);
} else {
String message = maxRedirects == 0
? error("URL %s follows too many redirects", uri.toString())
: error("URL %s returned %d without a valid redirect", uri.toString(), responseCode);
throw new IOException(message);
}
} else {
connection.disconnect();
throw new IOException(String
.format("Image URL %s returned HTTP code %d", uri.toString(), responseCode));
}
}
至此我們已經(jīng)清楚殿如,F(xiàn)resco對圖片的加載,那么他是怎么回調(diào)的呢贡珊?
可以看到
mNetworkFetcher.fetch(
fetchState, new NetworkFetcher.Callback() {
@Override
public void onResponse(InputStream response, int responseLength) throws IOException {
NetworkFetchProducer.this.onResponse(fetchState, response, responseLength);
}
@Override
public void onFailure(Throwable throwable) {
NetworkFetchProducer.this.onFailure(fetchState, throwable);
}
@Override
public void onCancellation() {
NetworkFetchProducer.this.onCancellation(fetchState);
}
});
在NetworkFetchProducer中就實現(xiàn)了回調(diào),這仍然處于子線程涉馁,那么看一看數(shù)據(jù)的回調(diào):
private void onResponse(
FetchState fetchState,
InputStream responseData,
int responseContentLength)
throws IOException {
final PooledByteBufferOutputStream pooledOutputStream;
if (responseContentLength > 0) {
pooledOutputStream = mPooledByteBufferFactory.newOutputStream(responseContentLength);
} else {
pooledOutputStream = mPooledByteBufferFactory.newOutputStream();
}
final byte[] ioArray = mByteArrayPool.get(READ_SIZE);
try {
int length;
while ((length = responseData.read(ioArray)) >= 0) {
if (length > 0) {
pooledOutputStream.write(ioArray, 0, length);
maybeHandleIntermediateResult(pooledOutputStream, fetchState);
float progress = calculateProgress(pooledOutputStream.size(), responseContentLength);
//獲取數(shù)據(jù)的回調(diào)就在這里
fetchState.getConsumer().onProgressUpdate(progress);
}
}
mNetworkFetcher.onFetchCompletion(fetchState, pooledOutputStream.size());
handleFinalResult(pooledOutputStream, fetchState);
} finally {
mByteArrayPool.release(ioArray);
pooledOutputStream.close();
}
}
private void handleFinalResult(
PooledByteBufferOutputStream pooledOutputStream,
FetchState fetchState) {
Map<String, String> extraMap = getExtraMap(fetchState, pooledOutputStream.size());
ProducerListener listener = fetchState.getListener();
listener.onProducerFinishWithSuccess(fetchState.getId(), PRODUCER_NAME, extraMap);
listener.onUltimateProducerReached(fetchState.getId(), PRODUCER_NAME, true);
notifyConsumer(
pooledOutputStream,
Consumer.IS_LAST | fetchState.getOnNewResultStatusFlags(),
fetchState.getResponseBytesRange(),
fetchState.getConsumer());
}
private void notifyConsumer(
PooledByteBufferOutputStream pooledOutputStream,
@Consumer.Status int status,
@Nullable BytesRange responseBytesRange,
Consumer<EncodedImage> consumer) {
CloseableReference<PooledByteBuffer> result =
CloseableReference.of(pooledOutputStream.toByteBuffer());
EncodedImage encodedImage = null;
try {
encodedImage = new EncodedImage(result);
encodedImage.setBytesRange(responseBytesRange);
encodedImage.parseMetaData();
//回調(diào)新結(jié)果
consumer.onNewResult(encodedImage, status);
} finally {
EncodedImage.closeSafely(encodedImage);
CloseableReference.closeSafely(result);
}
}
這里一直使用consumer.onProgressUpdate和consumer.onNewResult回調(diào),在AbstractProducerToDataSourceAdapter類里面有具體實現(xiàn):
private Consumer<T> createConsumer() {
return new BaseConsumer<T>() {
@Override
protected void onNewResultImpl(@Nullable T newResult, @Status int status) {
AbstractProducerToDataSourceAdapter.this.onNewResultImpl(newResult, status);
}
@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);
}
};
}
那么在來看一下AbstractProducerToDataSourceAdapter中這些回調(diào)處理了哪些事務(wù):
protected void onNewResultImpl(@Nullable T result, int status) {
boolean isLast = BaseConsumer.isLast(status);
if (super.setResult(result, isLast)) {
if (isLast) {
mRequestListener.onRequestSuccess(
mSettableProducerContext.getImageRequest(),
mSettableProducerContext.getId(),
mSettableProducerContext.isPrefetch());
}
}
}
private void onFailureImpl(Throwable throwable) {
if (super.setFailure(throwable)) {
mRequestListener.onRequestFailure(
mSettableProducerContext.getImageRequest(),
mSettableProducerContext.getId(),
throwable,
mSettableProducerContext.isPrefetch());
}
}
由上述代碼可知首先它們執(zhí)行了一個super.setResult和mRequestListener.onRequestSuccess门岔;
其中發(fā)現(xiàn)mResquestListener其實是由開發(fā)者自己設(shè)置的listener監(jiān)聽數(shù)據(jù)變化:最終由mRequestListener.onRequestSuccess接受業(yè)務(wù)執(zhí)行回調(diào),而mRequestListener的具體實現(xiàn)在ForwardingRequestListener類中,而我們現(xiàn)在具體看super.setResult中的邏輯:
protected boolean setResult(@Nullable T value, boolean isLast) {
boolean result = setResultInternal(value, isLast);
if (result) {
notifyDataSubscribers();
}
return result;
}
private boolean setResultInternal(@Nullable T value, boolean isLast) {
T resultToClose = null;
try {
synchronized (this) {
if (mIsClosed || mDataSourceStatus != DataSourceStatus.IN_PROGRESS) {
resultToClose = value;
return false;
} else {
if (isLast) {
mDataSourceStatus = DataSourceStatus.SUCCESS;
mProgress = 1;
}
if (mResult != value) {
resultToClose = mResult;
mResult = value;
}
return true;
}
}
} finally {
if (resultToClose != null) {
closeResult(resultToClose);
}
}
}
由上述代碼知道烤送,在數(shù)據(jù)加載完畢之后會返回true寒随,然后執(zhí)行notifyDataSubscribers,這個函數(shù)明顯是通知所有訂閱者狀態(tài)發(fā)生改變:
@Override
public void subscribe(final DataSubscriber<T> dataSubscriber, final Executor executor) {
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());
}
}
private void notifyDataSubscribers() {
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(
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);
}
}
});
}
protected void notifyProgressUpdate() {
for (Pair<DataSubscriber<T>, Executor> pair : mSubscribers) {
final DataSubscriber<T> subscriber = pair.first;
Executor executor = pair.second;
executor.execute(
new Runnable() {
@Override
public void run() {
subscriber.onProgressUpdate(AbstractDataSource.this);
}
});
}
}
這里面mSubscribers.add(Pair.create(dataSubscriber, executor));將每個subcriber與一個Executor通過一個Pair對象(相當(dāng)于一個鍵值對)綁定在一起,那么這個executor是執(zhí)行任務(wù)線程是主線程還是子線程呢:
這里需要回一下submitRequest這個函數(shù),在getDataSource之后妻往,它編創(chuàng)建了一個Subcriber并執(zhí)行了Subcribe方法:
protected void submitRequest() {
final T closeableImage = getCachedImage();
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();
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();
//創(chuàng)建訂閱者 并執(zhí)行回調(diào)
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);
}
可以在上述代碼中看到mDataSource.subscribe中傳遞一個mUiThreadImmediateExecutor;有此名稱可見逢防,它的任務(wù)執(zhí)行線程是主線程,那么他在哪兒初始化的呢?
public PipelineDraweeControllerBuilderSupplier(
Context context,
ImagePipelineFactory imagePipelineFactory,
Set<ControllerListener> boundControllerListeners,
@Nullable DraweeConfig draweeConfig) {
mContext = context;
mImagePipeline = imagePipelineFactory.getImagePipeline();
if (draweeConfig != null && draweeConfig.getPipelineDraweeControllerFactory() != null) {
mPipelineDraweeControllerFactory = draweeConfig.getPipelineDraweeControllerFactory();
} else {
mPipelineDraweeControllerFactory = new PipelineDraweeControllerFactory();
}
mPipelineDraweeControllerFactory.init(
context.getResources(),
DeferredReleaser.getInstance(),
imagePipelineFactory.getAnimatedDrawableFactory(context),
UiThreadImmediateExecutorService.getInstance(),
mImagePipeline.getBitmapMemoryCache(),
draweeConfig != null
? draweeConfig.getCustomDrawableFactories()
: null,
draweeConfig != null
? draweeConfig.getDebugOverlayEnabledSupplier()
: null);
mBoundControllerListeners = boundControllerListeners;
}
在PipelineDraweeControllerBuilderSupplier構(gòu)造函數(shù)中蒲讯,mPipelineDraweeControllerFactory.init第四個參數(shù)UiThreadImmediateExecutorService.getInstance()的靜態(tài)實例方法作為參數(shù)傳遞;一起來看一下UiThreadImmediateExecutorService類的實現(xiàn):
public class UiThreadImmediateExecutorService extends HandlerExecutorServiceImpl {
private static UiThreadImmediateExecutorService sInstance = null;
private UiThreadImmediateExecutorService() {
super(new Handler(Looper.getMainLooper()));
}
public static UiThreadImmediateExecutorService getInstance() {
if (sInstance == null) {
sInstance = new UiThreadImmediateExecutorService();
}
return sInstance;
}
@Override
public void execute(Runnable command) {
if (isHandlerThread()) {
command.run();
} else {
super.execute(command);
}
}
}
可以看到灰署,它的構(gòu)造函數(shù)這里傳遞了一個主線程的handler進去判帮,到這里就大概明白了它是通過handler郵寄runnable從而達(dá)到線程切換:
public class HandlerExecutorServiceImpl extends AbstractExecutorService
implements HandlerExecutorService {
private final Handler mHandler;
public HandlerExecutorServiceImpl(Handler handler) {
mHandler = handler;
}
......
@Override
public void execute(Runnable command) {
mHandler.post(command);
}
}
所以回到subcriber中,可以知道一下這段BaseDataSubscriber的具體實現(xiàn)是在主線程執(zhí)行的:
//創(chuàng)建訂閱者 并執(zhí)行回調(diào)
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);
}
};
最后成功回調(diào)onNewResultInternal方法完成圖片內(nèi)存緩存與顯示并釋放資源:
private void onNewResultInternal(
String id,
DataSource<T> dataSource,
@Nullable T image,
float progress,
boolean isFinished,
boolean wasImmediate) {
// ignore late callbacks (data source that returned the new result is not the one we expected)
if (!isExpectedDataSource(id, dataSource)) {
logMessageAndImage("ignore_old_datasource @ onNewResult", image);
releaseImage(image);
dataSource.close();
return;
}
mEventTracker.recordEvent(
isFinished ? Event.ON_DATASOURCE_RESULT : Event.ON_DATASOURCE_RESULT_INT);
// create drawable
Drawable drawable;
try {
drawable = createDrawable(image);
} catch (Exception exception) {
logMessageAndImage("drawable_failed @ onNewResult", image);
releaseImage(image);
onFailureInternal(id, dataSource, exception, isFinished);
return;
}
T previousImage = mFetchedImage;
Drawable previousDrawable = mDrawable;
mFetchedImage = image;
mDrawable = drawable;
try {
// set the new image
if (isFinished) {
logMessageAndImage("set_final_result @ onNewResult", image);
mDataSource = null;
mSettableDraweeHierarchy.setImage(drawable, 1f, wasImmediate);
getControllerListener().onFinalImageSet(id, getImageInfo(image), getAnimatable());
// IMPORTANT: do not execute any instance-specific code after this point
} else {
logMessageAndImage("set_intermediate_result @ onNewResult", image);
mSettableDraweeHierarchy.setImage(drawable, progress, wasImmediate);
getControllerListener().onIntermediateImageSet(id, getImageInfo(image));
// IMPORTANT: do not execute any instance-specific code after this point
}
} finally {
if (previousDrawable != null && previousDrawable != drawable) {
releaseDrawable(previousDrawable);
}
if (previousImage != null && previousImage != image) {
logMessageAndImage("release_previous_result @ onNewResult", previousImage);
releaseImage(previousImage);
}
}
}
至此溉箕,fresco加載圖片結(jié)束晦墙。
最后的GenericDraweeHierarchy轉(zhuǎn)換圖像可以看一下