Fresco 源码分析(三) Fresco服务端处理(4) Producer处理体系的总结
NetworkFetchProducer.produceResults() 相关源码
在中间的producer处理过程中都没有自己适合的处理的时候,最终还是会调用到网络获取的produceResults方法,这便是真正的网络数据获取以及处理的producer.
网络数据获取的细节,这个我们便不关注了,这里可以简单的提一点:
在fresco的对比的demo中,我们发现不仅仅可以使用fresco默认的网络数据获取,还可以使用okhttp,那么这里在个人翻看源码时,发现其网络数据获取器在ImagePipelineConfig中是可以设置的,这就是其设计的丰富的可配置化.
我们重点关注数据返回时是如何处理的,这就需要查看网络数据的callback是如何处理返回的数据.
@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);
}
});
}
从callback中看到,都调用了networkFetchProducer的处理方法,以数据成功处理的方法onResponse为例,我们继续分析
NetworkFetchProducer.onResponse() 相关源码
我们看到,通过对数据流的操作
1. 不断的读取mByteArrayPool和写入pooledOutputStream
2. 计算向pooledOutputStream中写入的进度,并且通知consumer
3. 如果完全写入完成,处理完成的后续操作
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();
}
}
在这段程序中,我们看到需要使用到流的一些操作,这些流我们标记为Q7,后续我们需要专门来说说这个部分
还是先关注我们的重点,在完成流的写入后,查看handleFinalResult()的部分
NetworkFetchProducer.handleFinalResult() 相关源码
private void handleFinalResult(
PooledByteBufferOutputStream pooledOutputStream,
FetchState fetchState) {
Map<String, String> extraMap = getExtraMap(fetchState, pooledOutputStream.size());
fetchState.getListener()
.onProducerFinishWithSuccess(fetchState.getId(), PRODUCER_NAME, extraMap);
notifyConsumer(pooledOutputStream, true, fetchState.getConsumer());
}
NetworkFetchProducer.notifyConsumer() 相关源码
private void notifyConsumer(
PooledByteBufferOutputStream pooledOutputStream,
boolean isFinal,
Consumer<EncodedImage> consumer) {
CloseableReference<PooledByteBuffer> result =
CloseableReference.of(pooledOutputStream.toByteBuffer());
EncodedImage encodedImage = null;
try {
encodedImage = new EncodedImage(result);
encodedImage.parseMetaData();
consumer.onNewResult(encodedImage, isFinal);
} finally {
EncodedImage.closeSafely(encodedImage);
CloseableReference.closeSafely(result);
}
}
以上两部分的源码,得知handleFinalResult做了如下的操作
1. 想fetchState的listener通知了完成
2. 将result封装为EncodedImage,并且解析其metaDta
3. 向外通知消费者有新的结果产生
4. 关闭了相关对象
刚刚我们已经分析了两个内存处理的producer和网络请求的producer,我们来总结一下producer体系整体处理的流程
Producer体系整体处理的逻辑伪代码
Producer.producerResult
本身是否可以处理
--> 可以处理
--> 直接向外通知consumer做相关的回调
--> 不能处理
--> 是否需要做自身相关的consumer回调的逻辑
--> 需要
--> 代理consumer的相关实现(Impl)方法
--> 不需要
---> 调用下一个producer来producerResult
启发: 对于一些较大的项目以及sdk封装中,对于流程化的一些代码,我们可以参照Fresco的处理方法,采用代理或者包装的方式,在当前中需要处理的逻辑方法,进行拦截处理,类似于SSH中的Spring,面向切面的编程,拦截过后,添加自身的逻辑.
刚刚我们已经将Producer的相关处理逻辑做了说明,下面我们将未被包装的Consumer进行说明
在前面我们提到了AbstractProducerToDataSourceAdapter,Producer到数据源的适配,其实无论中途怎么进行拦截和代理,最终还是要到适配器来向外界通知我们的结果,这里就用到了createConsumer的实现相关内容
AbstractProducerToDataSourceAdapter.createConsumer() 相关代码
private Consumer<T> createConsumer() {
return new BaseConsumer<T>() {
@Override
protected void onNewResultImpl(@Nullable T newResult, boolean isLast) {
AbstractProducerToDataSourceAdapter.this.onNewResultImpl(newResult, isLast);
}
@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);
}
};
}
在这里我们看到,这些方法交给了Adapter的相关方法来处理,还是按照成功处理的逻辑onNewResultImpl来继续分析
AbstractProducerToDataSourceAdapter.onNewResultImpl() 分析
protected void onNewResultImpl(@Nullable T result, boolean isLast) {
if (super.setResult(result, isLast)) {
if (isLast) {
mRequestListener.onRequestSuccess(
mSettableProducerContext.getImageRequest(),
mSettableProducerContext.getId(),
mSettableProducerContext.isPrefetch());
}
}
}
- 调用super.setResult,向外通知结果(我们关心的处理过程)
- 如果是最终的结果,向外通知RequestListener(RequestListener)可以作为数据统计使用
查看super.setResult的源码发现,
AbstractDataSource.setResult() 相关源码
- 设置内部结果,更改相关状态
向外通知结果(重点)
/**
- Subclasses should invoke this method to set the result to {@code value}.
* 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.
* 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}.
* {@link #closeResult} will be called for the previous result if the new value was
- successfully set, OR for the new result otherwise.
* This will also notify the subscribers if the value was successfully set.
*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) {
boolean result = setResultInternal(value, isLast);
if (result) {
notifyDataSubscribers();
}
return result;
}
- Subclasses should invoke this method to set the result to {@code value}.
AbstractDataSource.notifyDataSubscribers() 相关源码分析
通知所有的数据的订阅者,数据已经完成请求,然后请求的回调是在注册时请求的线程池中执行的
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);
}
}
});
}
说道这里,其实服务端的处理逻辑就已经差不多了,下篇我们将DataSource和DataSubscriber的部分结合起来,即分析client端的请求回调部分(http://blog.csdn.net/ieyudeyinji/article/details/48286059)
安卓源码分析群: Android源码分析QQ1群号:164812238