前言
Fresco 中设计有一个叫做 image pipeline 的模块。它负责从网络,从本地文件系统,本地资源加载图片。为了最大限度节省空间和CPU时间,它含有3级缓存设计(2级内存,1级文件)。
Fresco 中设计有一个叫做 Drawees 模块,方便地显示loading图,当图片不再显示在屏幕上时,及时地释放内存和空间占用。
使用
Fresco使用:
首先需要在layout布局上使用fresco的simpleDraweeView:
然后再java代码中使用:
SimpleDraweeView simpleDraweeView = findViewById(R.id.simpleDraweeView);
Uri uri = Uri.parse("https://www.baidu.com/img/xinshouye_034fec51df225fe8410f36ad3f2fccf6.png");
simpleDraweeView.setImageURI(uri);
由上述使用方法可以看出,只需要给定一个容器然后传入一个url地址,即可完成对图片的加载;那么它的内部运行流程是什么样的呢?
fresco整个业务流程:
E:\我的图片\20160523111021635.png
入口
很明显,SimpleDraweeView是我们先要弄清楚的,首先要明白它是继承自ImageView的,并且具有layout布局,显然是自定义View,第一步必然是从布局文件样式中读取属性值。
那么我们直接看看simpleDraweeView.setImageURI(uri)方法:
public void setImageURI(Uri uri, @Nullable Object callerContext) {
DraweeController controller = mSimpleDraweeControllerBuilder
.setCallerContext(callerContext)
.setUri(uri)
.setOldController(getController())
.build();
setController(controller);
}
首先它创建了一个Controller并调用setController,看一下Controller是怎么创建的:
@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;
}
//创建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 {
//工厂模式创建Controller
controller = mPipelineDraweeControllerFactory.newController(
obtainDataSourceSupplier(),
generateUniqueControllerId(),
getCacheKey(),
getCallerContext(),
mCustomDrawableFactories);
}
return controller;
}
public PipelineDraweeController newController(
Supplier>> dataSourceSupplier,
String id,
CacheKey cacheKey,
Object callerContext,
@Nullable ImmutableList 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
//创建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 memoryCache,
@Nullable ImmutableList globalDrawableFactories,
@Nullable ImmutableList customDrawableFactories,
Supplier>> dataSourceSupplier,
String id,
CacheKey cacheKey,
Object callerContext) {
//至此Controller创建完毕 为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());
}
继续追踪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,然后调用attachController方法:
private void attachController() {
if (mIsControllerAttached) {
return;
}
mEventTracker.recordEvent(Event.ON_ATTACH_CONTROLLER);
mIsControllerAttached = true;
if (mController != null &&
mController.getHierarchy() != null) {
mController.onAttach();
}
}
继续追踪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();//提交数据请求
}
}
终于看到提交数据请求了:
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();
//观察者订阅数据请求
final DataSubscriber dataSubscriber =
new BaseDataSubscriber() {
@Override
public void onNewResultImpl(DataSource 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 dataSource) {
onFailureInternal(id, dataSource, dataSource.getFailureCause(), /* isFinished */ true);
}
@Override
public void onProgressUpdate(DataSource dataSource) {
boolean isFinished = dataSource.isFinished();
float progress = dataSource.getProgress();
onProgressUpdateInternal(id, dataSource, progress, isFinished);
}
};
mDataSource.subscribe(dataSubscriber, mUiThreadImmediateExecutor);
}
可以看到数据请求逻辑在getDataSource里面:
@Override
protected DataSource> getDataSource() {
if (FLog.isLoggable(FLog.VERBOSE)) {
FLog.v(TAG, "controller %x: getDataSource", System.identityHashCode(this));
}
return mDataSourceSupplier.get();
}
最终getDataSource将数据请求交给了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;
}
我们发现,在创建controller的时候会传递obtainDataSourceSupplier方法为参数:
protected Supplier> obtainDataSourceSupplier() {
if (mDataSourceSupplier != null) {
return mDataSourceSupplier;
}
Supplier> supplier = null;
// final image supplier;
if (mImageRequest != null) {
//获取网络数据提供者
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>> 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> getDataSourceSupplierForRequest(
final REQUEST imageRequest,
final CacheLevel cacheLevel) {
final Object callerContext = getCallerContext();
return new Supplier>() {
@Override
public DataSource get() {
return getDataSourceForRequest(imageRequest, callerContext, cacheLevel);
}
@Override
public String toString() {
return Objects.toStringHelper(this)
.add("request", imageRequest.toString())
.toString();
}
};
}
至此mDataSourceSupplier才浮出水面,最后实现了get方法正是获取图片数据请求的方法:
@Override
protected DataSource> getDataSourceForRequest(
ImageRequest imageRequest,
Object callerContext,
CacheLevel cacheLevel) {
return mImagePipeline.fetchDecodedImage(
imageRequest,
callerContext,
convertCacheLevelToRequestLevel(cacheLevel));
}
继续追踪:
public DataSource> fetchDecodedImage(
ImageRequest imageRequest,
Object callerContext,
ImageRequest.RequestLevel lowestPermittedRequestLevelOnSubmit) {
try {
Producer> producerSequence =
mProducerSequenceFactory.getDecodedImageProducerSequence(imageRequest);
return submitFetchRequest(
producerSequence,
imageRequest,
lowestPermittedRequestLevelOnSubmit,
callerContext);
} catch (Exception exception) {
return DataSources.immediateFailedDataSource(exception);
}
}
继续追踪submitFetchRequest:
private DataSource> submitFetchRequest(
Producer> 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);
}
}
继续追踪CloseableProducerToDataSourceAdapter.create
public static DataSource create(
Producer producer,
SettableProducerContext settableProducerContext,
RequestListener listener) {
return new ProducerToDataSourceAdapter(
producer,
settableProducerContext,
listener);
}
继续
protected AbstractProducerToDataSourceAdapter(
Producer 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>
getNetworkFetchEncodedImageProducerSequence() {
synchronized (this) {
if (mNetworkEncodedImageProducerSequence == null) {
mNetworkEncodedImageProducerSequence = new RemoveImageTransformMetaDataProducer(
getBackgroundNetworkFetchToEncodedMemorySequence());
}
}
return mNetworkEncodedImageProducerSequence;
}
一直追踪,发现具体请求网络数据在NetworkFetchProducer这个类,其中有一个mNetworkFetcher.fetch方法:
@Override
public void produceResults(Consumer 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方法做什么工作:
我们发现,有两个类实现了这个接口,分别是HttpUrlConnectionNetworkFetcher和OkHttpNetworkFetcher,走到这一步就很明显了:Fresco加载图片用的是okhttp和httpurlconnection。
让我们看一下Fresco的okhttp加载数据实现:
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实现:
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));
}
}
至此我们已经清楚,Fresco对图片的加载,那么他是怎么回调的呢?
可以看到
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中就实现了回调,这仍然处于子线程,那么看一看数据的回调:
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);
//获取数据的回调就在这里
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 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 consumer) {
CloseableReference result =
CloseableReference.of(pooledOutputStream.toByteBuffer());
EncodedImage encodedImage = null;
try {
encodedImage = new EncodedImage(result);
encodedImage.setBytesRange(responseBytesRange);
encodedImage.parseMetaData();
//回调新结果
consumer.onNewResult(encodedImage, status);
} finally {
EncodedImage.closeSafely(encodedImage);
CloseableReference.closeSafely(result);
}
}
这里一直使用consumer.onProgressUpdate和consumer.onNewResult回调,在AbstractProducerToDataSourceAdapter类里面有具体实现:
private Consumer createConsumer() {
return new BaseConsumer() {
@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中这些回调处理了哪些事务:
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());
}
}
由上述代码可知首先它们执行了一个super.setResult和mRequestListener.onRequestSuccess;
其中发现mResquestListener其实是由开发者自己设置的listener监听数据变化:最终由mRequestListener.onRequestSuccess接受业务执行回调,而mRequestListener的具体实现在ForwardingRequestListener类中,而我们现在具体看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);
}
}
}
由上述代码知道,在数据加载完毕之后会返回true,然后执行notifyDataSubscribers,这个函数明显是通知所有订阅者状态发生改变:
@Override
public void subscribe(final DataSubscriber 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, Executor> pair : mSubscribers) {
notifyDataSubscriber(pair.first, pair.second, isFailure, isCancellation);
}
}
private void notifyDataSubscriber(
final DataSubscriber 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, Executor> pair : mSubscribers) {
final DataSubscriber 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对象(相当于一个键值对)绑定在一起,那么这个executor是执行任务线程是主线程还是子线程呢:
这里需要回一下submitRequest这个函数,在getDataSource之后,它编创建了一个Subcriber并执行了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();
//创建订阅者 并执行回调
final DataSubscriber dataSubscriber =
new BaseDataSubscriber() {
@Override
public void onNewResultImpl(DataSource 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 dataSource) {
onFailureInternal(id, dataSource, dataSource.getFailureCause(), /* isFinished */ true);
}
@Override
public void onProgressUpdate(DataSource dataSource) {
boolean isFinished = dataSource.isFinished();
float progress = dataSource.getProgress();
onProgressUpdateInternal(id, dataSource, progress, isFinished);
}
};
//提交订阅
mDataSource.subscribe(dataSubscriber, mUiThreadImmediateExecutor);
}
可以在上述代码中看到mDataSource.subscribe中传递一个mUiThreadImmediateExecutor;有此名称可见,它的任务执行线程是主线程,那么他在哪儿初始化的呢?
public PipelineDraweeControllerBuilderSupplier(
Context context,
ImagePipelineFactory imagePipelineFactory,
Set 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构造函数中,mPipelineDraweeControllerFactory.init第四个参数UiThreadImmediateExecutorService.getInstance()的静态实例方法作为参数传递;一起来看一下UiThreadImmediateExecutorService类的实现:
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);
}
}
}
可以看到,它的构造函数这里传递了一个主线程的handler进去,到这里就大概明白了它是通过handler邮寄runnable从而达到线程切换:
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的具体实现是在主线程执行的:
//创建订阅者 并执行回调
final DataSubscriber dataSubscriber =
new BaseDataSubscriber() {
@Override
public void onNewResultImpl(DataSource 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 dataSource) {
onFailureInternal(id, dataSource, dataSource.getFailureCause(), /* isFinished */ true);
}
@Override
public void onProgressUpdate(DataSource dataSource) {
boolean isFinished = dataSource.isFinished();
float progress = dataSource.getProgress();
onProgressUpdateInternal(id, dataSource, progress, isFinished);
}
};
最后成功回调onNewResultInternal方法完成图片内存缓存与显示并释放资源:
private void onNewResultInternal(
String id,
DataSource 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加载图片结束。
最后的GenericDraweeHierarchy转换图像可以看一下