Skip to content

Commit 7bf53df

Browse files
oprisnikmeta-codesync[bot]
authored andcommitted
Let ImagePipelineUtils build a request from the whole ImageSource
Differential Revision: D117508945 fbshipit-source-id: 7ccdcaadfdb003e93b0045d8470aa6e3f0316403
1 parent 9acb63c commit 7bf53df

4 files changed

Lines changed: 75 additions & 6 deletions

File tree

‎vito/core-java-impl/src/main/java/com/facebook/fresco/vito/core/impl/ImagePipelineUtilsImpl.kt‎

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,9 @@ import com.facebook.imagepipeline.request.ImageRequestBuilder
1919
/**
2020
* Utility methods to create [ImageRequest]s for [com.facebook.fresco.vito.options.ImageOptions].
2121
*/
22-
class ImagePipelineUtilsImpl(private val imageDecodeOptionsProvider: ImageDecodeOptionsProvider) :
23-
ImagePipelineUtils {
22+
open class ImagePipelineUtilsImpl(
23+
private val imageDecodeOptionsProvider: ImageDecodeOptionsProvider,
24+
) : ImagePipelineUtils {
2425

2526
fun interface CircularBitmapRounding {
2627
fun getDecodeOptions(antiAliased: Boolean): ImageDecodeOptions?
@@ -58,7 +59,7 @@ class ImagePipelineUtilsImpl(private val imageDecodeOptionsProvider: ImageDecode
5859
imageOptions: EncodedImageOptions,
5960
): ImageRequest? = createEncodedImageRequestBuilder(uri, imageOptions)?.build()
6061

61-
protected fun createDecodedImageRequestBuilder(
62+
protected open fun createDecodedImageRequestBuilder(
6263
imageRequestBuilder: ImageRequestBuilder?,
6364
imageOptions: DecodedImageOptions,
6465
): ImageRequestBuilder? = imageRequestBuilder?.apply {
@@ -93,7 +94,7 @@ class ImagePipelineUtilsImpl(private val imageDecodeOptionsProvider: ImageDecode
9394
isFirstFrameThumbnailEnabled = imageOptions.isFirstFrameThumbnailEnabled
9495
}
9596

96-
protected fun createEncodedImageRequestBuilder(
97+
protected open fun createEncodedImageRequestBuilder(
9798
uri: Uri?,
9899
imageOptions: EncodedImageOptions,
99100
): ImageRequestBuilder? {
@@ -111,7 +112,7 @@ class ImagePipelineUtilsImpl(private val imageDecodeOptionsProvider: ImageDecode
111112
return builder
112113
}
113114

114-
protected fun createEncodedImageRequestBuilder(
115+
protected open fun createEncodedImageRequestBuilder(
115116
imageRequest: ImageRequest?,
116117
imageOptions: EncodedImageOptions,
117118
): ImageRequestBuilder? {

‎vito/core-java-impl/src/main/java/com/facebook/fresco/vito/core/impl/ImageSourceToImagePipelineAdapter.kt‎

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -223,10 +223,14 @@ object ImageSourceToImagePipelineAdapter {
223223
}
224224
}
225225

226+
// Passes the whole source, not just imageUri, so an ImagePipelineUtils implementation can read
227+
// state its own SingleImageSource subtype carries. Both callers of this — the fetch supplier and
228+
// maybeExtractFinalImageRequest, which produces the cache key — route through here, so the two
229+
// stay consistent.
226230
fun SingleImageSource.extractSingleRequest(
227231
imagePipelineUtils: ImagePipelineUtils,
228232
imageOptions: ImageOptions,
229-
): ImageRequest? = imagePipelineUtils.buildImageRequest(imageUri, imageOptions)
233+
): ImageRequest? = imagePipelineUtils.buildImageRequest(this, imageOptions)
230234

231235
fun FirstAvailableImageSource.extractFirstAvailableRequest(
232236
imagePipelineUtils: ImagePipelineUtils,

‎vito/core-java-impl/src/test/java/com/facebook/fresco/vito/core/impl/ImagePipelineUtilsImplTest.kt‎

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,17 @@ package com.facebook.fresco.vito.core.impl
1010
import android.net.Uri
1111
import com.facebook.fresco.vito.core.ImagePipelineUtils
1212
import com.facebook.fresco.vito.core.impl.ImagePipelineUtilsImpl.CircularBitmapRounding
13+
import com.facebook.fresco.vito.options.DecodedImageOptions
1314
import com.facebook.fresco.vito.options.ImageOptions
1415
import com.facebook.fresco.vito.options.RoundingOptions
16+
import com.facebook.fresco.vito.source.SingleImageSource
17+
import com.facebook.fresco.vito.source.SingleImageSourceImpl
1518
import com.facebook.imagepipeline.common.ImageDecodeOptions
1619
import com.facebook.imagepipeline.common.ResizeOptions
1720
import com.facebook.imagepipeline.common.RotationOptions
1821
import com.facebook.imagepipeline.core.DownsampleMode
22+
import com.facebook.imagepipeline.request.ImageRequest
23+
import com.facebook.imagepipeline.request.ImageRequestBuilder
1924
import com.facebook.imagepipeline.testing.TestNativeLoader
2025
import kotlin.test.fail
2126
import org.assertj.core.api.Assertions
@@ -172,6 +177,48 @@ class ImagePipelineUtilsImplTest {
172177
Assertions.assertThat(imageRequest.rotationOptions).isEqualTo(rotationOptions)
173178
}
174179

180+
@Test
181+
fun testBuildImageRequest_whenGivenImageSource_thenDefaultsToTheUriOverload() {
182+
val rotationOptions = RotationOptions.forceRotation(RotationOptions.ROTATE_270)
183+
val imageOptions = ImageOptions.create().rotate(rotationOptions).build()
184+
185+
val fromSource = imagePipelineUtils.buildImageRequest(SingleImageSourceImpl(URI), imageOptions)
186+
187+
Assertions.assertThat(fromSource).isNotNull
188+
Assertions.assertThat(fromSource?.sourceUri).isEqualTo(URI)
189+
Assertions.assertThat(fromSource?.rotationOptions).isEqualTo(rotationOptions)
190+
}
191+
192+
/**
193+
* The point of the overload: an implementation can read state that its own [SingleImageSource]
194+
* subtype carries, which the URI alone cannot express.
195+
*/
196+
@Test
197+
fun testBuildImageRequest_whenOverridden_thenImplementationSeesTheSource() {
198+
val utils =
199+
object :
200+
ImagePipelineUtilsImpl(
201+
DefaultImageDecodeOptionsProviderImpl(TestCircularBitmapRounding()),
202+
) {
203+
override fun buildImageRequest(
204+
imageSource: SingleImageSource,
205+
imageOptions: DecodedImageOptions,
206+
): ImageRequest? =
207+
super.buildImageRequest(imageSource, imageOptions)?.let {
208+
ImageRequestBuilder.fromRequest(it)
209+
.setCacheChoice(ImageRequest.CacheChoice.SMALL)
210+
.build()
211+
}
212+
}
213+
214+
val imageRequest = utils.buildImageRequest(SingleImageSourceImpl(URI), ImageOptions.defaults())
215+
216+
Assertions.assertThat(imageRequest?.cacheChoice).isEqualTo(ImageRequest.CacheChoice.SMALL)
217+
// The URI overload is untouched by the override, so callers that still use it are unaffected.
218+
Assertions.assertThat(utils.buildImageRequest(URI, ImageOptions.defaults())?.cacheChoice)
219+
.isEqualTo(ImageRequest.CacheChoice.DEFAULT)
220+
}
221+
175222
internal inner class TestCircularBitmapRounding : CircularBitmapRounding {
176223
override fun getDecodeOptions(antiAliased: Boolean): ImageDecodeOptions =
177224
if (antiAliased) roundingDecodeOptionsAntiAliased else roundingDecodeOptions

‎vito/core/src/main/java/com/facebook/fresco/vito/core/ImagePipelineUtils.kt‎

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,29 @@ package com.facebook.fresco.vito.core
1010
import android.net.Uri
1111
import com.facebook.fresco.vito.options.DecodedImageOptions
1212
import com.facebook.fresco.vito.options.EncodedImageOptions
13+
import com.facebook.fresco.vito.source.SingleImageSource
1314
import com.facebook.imagepipeline.request.ImageRequest
1415

1516
interface ImagePipelineUtils {
1617

1718
fun buildImageRequest(uri: Uri?, imageOptions: DecodedImageOptions): ImageRequest?
1819

20+
/**
21+
* Builds the image request for a whole [SingleImageSource] rather than just its URI.
22+
*
23+
* An app that defines its own [SingleImageSource] subtype can carry more than a URI on it — a
24+
* typed URL, cache-key material, decode hints — and override this to read that state when
25+
* building the request. The default keeps the URI-only behaviour, so existing implementations are
26+
* unaffected.
27+
*
28+
* Both the fetch path and the cache-key path go through this method, so an override applies to
29+
* each consistently.
30+
*/
31+
fun buildImageRequest(
32+
imageSource: SingleImageSource,
33+
imageOptions: DecodedImageOptions,
34+
): ImageRequest? = buildImageRequest(imageSource.imageUri, imageOptions)
35+
1936
fun wrapDecodedImageRequest(
2037
originalRequest: ImageRequest,
2138
imageOptions: DecodedImageOptions,

0 commit comments

Comments
 (0)