From fe331253ca6155b32bc719404b96e4eebbf29639 Mon Sep 17 00:00:00 2001 From: Alexander Oprisnik Date: Wed, 19 Jun 2024 12:58:30 -0700 Subject: [PATCH] Added functionality to display partial images instead of placeholder if in cache Reviewed By: kartavya-ramnani Differential Revision: D58424402 fbshipit-source-id: de4434e90c7c785ca7317b36033ac9b308652644 --- .../vito/core/impl/KFrescoController.kt | 41 ++++++++++++------- .../vito/core/impl/FrescoController2Impl.kt | 41 ++++++++++++------- .../vito/core/DefaultFrescoVitoConfig.kt | 2 + .../fresco/vito/core/FrescoVitoConfig.kt | 2 + 4 files changed, 58 insertions(+), 28 deletions(-) diff --git a/vito/core-impl/src/main/java/com/facebook/fresco/vito/core/impl/KFrescoController.kt b/vito/core-impl/src/main/java/com/facebook/fresco/vito/core/impl/KFrescoController.kt index edbdbd07d8..fd6f27faa8 100644 --- a/vito/core-impl/src/main/java/com/facebook/fresco/vito/core/impl/KFrescoController.kt +++ b/vito/core-impl/src/main/java/com/facebook/fresco/vito/core/impl/KFrescoController.kt @@ -174,16 +174,24 @@ class KFrescoController( // Check if the image is in cache val cachedImage = vitoImagePipeline.getCachedImage(imageRequest) - if (drawable.setActualImage(imageRequest, cachedImage)) { + + val isIntermediateImage = + config.useIntermediateImagesAsPlaceholder() && + cachedImage?.get()?.qualityInfo?.isOfFullQuality != true + val hasImage = drawable.setActualImage(imageRequest, cachedImage, isIntermediateImage) + if (hasImage && !isIntermediateImage) { + // Immediately return since we have the full image return true } - // The image is not in cache -> Set up layers visible until the image is available - drawable.placeholderLayer.setPlaceholder(imageRequest.resources, options) - drawable.listenerManager.onPlaceholderSet( - imageId, imageRequest, drawable.placeholderLayer.getDataModel().maybeGetDrawable()) + if (!hasImage) { + // The image is not in cache -> Set up layers visible until the image is available + drawable.placeholderLayer.setPlaceholder(imageRequest.resources, options) + drawable.listenerManager.onPlaceholderSet( + imageId, imageRequest, drawable.placeholderLayer.getDataModel().maybeGetDrawable()) - drawable.setupProgressLayer(imageRequest.resources, options) + drawable.setupProgressLayer(imageRequest.resources, options) + } // Fetch the image lightweightBackgroundThreadExecutor.execute { @@ -243,7 +251,8 @@ class KFrescoController( */ private fun KFrescoVitoDrawable.setActualImage( imageRequest: VitoImageRequest, - imageReference: CloseableReference? + imageReference: CloseableReference?, + isIntermediateImage: Boolean = false, ): Boolean { traceSection("KFrescoController#setActualImage") { try { @@ -258,13 +267,17 @@ class KFrescoController( // TODO(T105148151): trigger listeners invalidateSelf() val imageInfo = image.imageInfo - listenerManager.onFinalImageSet( - imageId, - imageRequest, - ImageOrigin.MEMORY_BITMAP_SHORTCUT, - imageInfo, - obtainExtras(null, imageReference), - actualImageDrawable) + if (isIntermediateImage) { + listenerManager.onIntermediateImageSet(imageId, imageRequest, imageInfo) + } else { + listenerManager.onFinalImageSet( + imageId, + imageRequest, + ImageOrigin.MEMORY_BITMAP_SHORTCUT, + imageInfo, + obtainExtras(null, imageReference), + actualImageDrawable) + } debugOverlayHandler?.update(this) return true } diff --git a/vito/core-java-impl/src/main/java/com/facebook/fresco/vito/core/impl/FrescoController2Impl.kt b/vito/core-java-impl/src/main/java/com/facebook/fresco/vito/core/impl/FrescoController2Impl.kt index 2ce4e77336..566d1b5b54 100644 --- a/vito/core-java-impl/src/main/java/com/facebook/fresco/vito/core/impl/FrescoController2Impl.kt +++ b/vito/core-java-impl/src/main/java/com/facebook/fresco/vito/core/impl/FrescoController2Impl.kt @@ -4,6 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ + package com.facebook.fresco.vito.core.impl import android.graphics.Bitmap @@ -185,26 +186,37 @@ open class FrescoController2Impl( // Check if the image is in cache val cachedImage = mImagePipeline.getCachedImage(imageRequest) + var needsPlaceholderDrawable = true try { if (CloseableReference.isValid(cachedImage)) { frescoDrawable.imageOrigin = ImageOrigin.MEMORY_BITMAP_SHORTCUT + val isIntermediateImage = + mConfig.useIntermediateImagesAsPlaceholder() && + cachedImage?.get()?.qualityInfo?.isOfFullQuality != true // Immediately display the actual image. - setActualImage(frescoDrawable, imageRequest, cachedImage, true, null) + setActualImage(frescoDrawable, imageRequest, cachedImage, true, null, isIntermediateImage) frescoDrawable.setFetchSubmitted(true) mDebugOverlayFactory.update(frescoDrawable, extras) - return true + if (!isIntermediateImage) { + return true + } else { + // We are displaying an intermediate image and can skip setting up the placeholder + needsPlaceholderDrawable = false + } } } finally { CloseableReference.closeSafely(cachedImage) } - // The image is not in cache -> Set up layers visible until the image is available - frescoDrawable.setProgressDrawable( - mHierarcher.buildProgressDrawable(imageRequest.resources, imageRequest.imageOptions)) - // Immediately show the progress image and set progress to 0 - frescoDrawable.setProgress(0f) - frescoDrawable.showProgressImmediately() - setUpPlaceholder(frescoDrawable, imageRequest, imageId) + if (!needsPlaceholderDrawable) { + // The image is not in cache -> Set up layers visible until the image is available + frescoDrawable.setProgressDrawable( + mHierarcher.buildProgressDrawable(imageRequest.resources, imageRequest.imageOptions)) + // Immediately show the progress image and set progress to 0 + frescoDrawable.setProgress(0f) + frescoDrawable.showProgressImmediately() + setUpPlaceholder(frescoDrawable, imageRequest, imageId) + } // Fetch the image val fetchRunnable = Runnable { @@ -286,8 +298,9 @@ open class FrescoController2Impl( drawable: FrescoDrawable2Impl, imageRequest: VitoImageRequest, image: CloseableReference?, - isImmediate: Boolean, - dataSource: DataSource>? + displayImmediately: Boolean, + dataSource: DataSource>?, + isIntermediateImage: Boolean = false, ) { val actualImageWrapperDrawable = drawable.actualImageWrapper mHierarcher.setupActualImageWrapper( @@ -297,7 +310,7 @@ open class FrescoController2Impl( imageRequest.resources, imageRequest.imageOptions, image!!) actualImageWrapperDrawable.setCurrent(actualDrawable ?: NopDrawable) drawable.setImage(actualImageWrapperDrawable, image) - if (isImmediate || imageRequest.imageOptions.fadeDurationMs <= 0) { + if (displayImmediately || imageRequest.imageOptions.fadeDurationMs <= 0) { drawable.showImageImmediately() } else { drawable.fadeInImage(imageRequest.imageOptions.fadeDurationMs) @@ -307,13 +320,13 @@ open class FrescoController2Impl( } val extras = obtainExtras(dataSource, image, drawable) val imageInfo = image.get().imageInfo - if (notifyFinalResult(dataSource)) { + if (!isIntermediateImage && notifyFinalResult(dataSource)) { drawable.internalListener.onFinalImageSet( drawable.imageId, imageRequest, drawable.imageOrigin, imageInfo, extras, actualDrawable) } else { drawable.internalListener.onIntermediateImageSet(drawable.imageId, imageRequest, imageInfo) } - drawable.imagePerfListener.onImageSuccess(drawable, isImmediate) + drawable.imagePerfListener.onImageSuccess(drawable, displayImmediately) var progress = 1f if (dataSource != null && !dataSource.isFinished) { progress = dataSource.progress diff --git a/vito/core/src/main/java/com/facebook/fresco/vito/core/DefaultFrescoVitoConfig.kt b/vito/core/src/main/java/com/facebook/fresco/vito/core/DefaultFrescoVitoConfig.kt index bfe7edb737..531ec0be31 100644 --- a/vito/core/src/main/java/com/facebook/fresco/vito/core/DefaultFrescoVitoConfig.kt +++ b/vito/core/src/main/java/com/facebook/fresco/vito/core/DefaultFrescoVitoConfig.kt @@ -38,6 +38,8 @@ constructor(override val prefetchConfig: PrefetchConfig = DefaultPrefetchConfig( override fun handleImageResultInBackground(): Boolean = false + override fun useIntermediateImagesAsPlaceholder(): Boolean = false + open class DefaultPrefetchConfig : PrefetchConfig { override fun prefetchInOnPrepare(): Boolean = true diff --git a/vito/core/src/main/java/com/facebook/fresco/vito/core/FrescoVitoConfig.kt b/vito/core/src/main/java/com/facebook/fresco/vito/core/FrescoVitoConfig.kt index 0e791bb06d..c3c782d214 100644 --- a/vito/core/src/main/java/com/facebook/fresco/vito/core/FrescoVitoConfig.kt +++ b/vito/core/src/main/java/com/facebook/fresco/vito/core/FrescoVitoConfig.kt @@ -33,4 +33,6 @@ interface FrescoVitoConfig { fun enableWindowWideColorGamut(): Boolean fun handleImageResultInBackground(): Boolean + + fun useIntermediateImagesAsPlaceholder(): Boolean }