/* * Copyright (c) 2015-present, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the * LICENSE file in the root directory of this source tree. An additional grant * of patent rights can be found in the PATENTS file in the same directory. */ package com.facebook.imagepipeline.producers; import java.io.IOException; import java.io.InputStream; import java.util.concurrent.Executor; import com.facebook.common.internal.Closeables; import com.facebook.common.memory.PooledByteBuffer; import com.facebook.common.memory.PooledByteBufferFactory; import com.facebook.common.references.CloseableReference; import com.facebook.imagepipeline.image.EncodedImage; import com.facebook.imagepipeline.request.ImageRequest; /** * Represents a local fetch producer. */ public abstract class LocalFetchProducer implements Producer<EncodedImage> { private final Executor mExecutor; private final PooledByteBufferFactory mPooledByteBufferFactory; protected LocalFetchProducer( Executor executor, PooledByteBufferFactory pooledByteBufferFactory) { mExecutor = executor; mPooledByteBufferFactory = pooledByteBufferFactory; } @Override public void produceResults( final Consumer<EncodedImage> consumer, final ProducerContext producerContext) { final ProducerListener listener = producerContext.getListener(); final String requestId = producerContext.getId(); final ImageRequest imageRequest = producerContext.getImageRequest(); final StatefulProducerRunnable cancellableProducerRunnable = new StatefulProducerRunnable<EncodedImage>( consumer, listener, getProducerName(), requestId) { @Override protected EncodedImage getResult() throws Exception { EncodedImage encodedImage = getEncodedImage(imageRequest); if (encodedImage == null) { listener.onUltimateProducerReached(requestId, getProducerName(), false); return null; } encodedImage.parseMetaData(); listener.onUltimateProducerReached(requestId, getProducerName(), true); return encodedImage; } @Override protected void disposeResult(EncodedImage result) { EncodedImage.closeSafely(result); } }; producerContext.addCallbacks( new BaseProducerContextCallbacks() { @Override public void onCancellationRequested() { cancellableProducerRunnable.cancel(); } }); mExecutor.execute(cancellableProducerRunnable); } /** Creates a memory-backed encoded image from the stream. The stream is closed. */ protected EncodedImage getByteBufferBackedEncodedImage( InputStream inputStream, int length) throws IOException { CloseableReference<PooledByteBuffer> ref = null; try { if (length <= 0) { ref = CloseableReference.of(mPooledByteBufferFactory.newByteBuffer(inputStream)); } else { ref = CloseableReference.of(mPooledByteBufferFactory.newByteBuffer(inputStream, length)); } return new EncodedImage(ref); } finally { Closeables.closeQuietly(inputStream); CloseableReference.closeSafely(ref); } } protected EncodedImage getEncodedImage( InputStream inputStream, int length) throws IOException { return getByteBufferBackedEncodedImage(inputStream, length); } /** * Gets an encoded image from the local resource. It can be either backed by a FileInputStream or * a PooledByteBuffer * @param imageRequest request that includes the local resource that is being accessed * @throws IOException */ protected abstract EncodedImage getEncodedImage(ImageRequest imageRequest) throws IOException; /** * @return name of the Producer */ protected abstract String getProducerName(); }