mirror of
https://github.com/facebook/react-native.git
synced 2025-11-01 09:14:26 +00:00
feat(image): [android] adding only-if-cached cache control option (#47348)
Summary: Following up from https://github.com/facebook/react-native/issues/47182, as basic caching control is already in place in Android, it can be extended to include the `only-if-cached` option. We check whether the image is in the cache. If it is, we proceed to load it. Otherwise, we do nothing. ## Changelog: [ANDROID] [ADDED] - Image `only-if-cached` cache control option Pull Request resolved: https://github.com/facebook/react-native/pull/47348 Test Plan: In the `rn-tester`, I added a third example for Android where the third image will never be loaded as the cache policy is set to `only-if-cached` and the image has not been loaded before. <details> <summary>Video demonstrating how the `only-if-cached` options behaves</summary> https://github.com/user-attachments/assets/45669e81-5414-4103-8931-138bffa81447 </details> <details> <summary>Error from image not found in cache example</summary> <img width="807" alt="image" src="https://github.com/user-attachments/assets/6b79d811-1809-437c-b2fe-c86d3da7c58d"> </details> Reviewed By: rshest Differential Revision: D65384639 Pulled By: Abbondanzo fbshipit-source-id: f4a72694f45eb3d7097c350f4a4008a0abf0a1ab
This commit is contained in:
1 parent
91df5a4a0f
commit
dc9db01665
7 files changed
+42
-5
No files matched your search
+1
-1
@@ -51,7 +51,7 @@ export interface ImageURISource {
|
||||
* to a URL load request, no attempt is made to load the data from the originating source,
|
||||
* and the load is considered to have failed.
|
||||
*
|
||||
* @platform ios (for `force-cache` and `only-if-cached`)
|
||||
* @platform ios (for `force-cache`)
|
||||
*/
|
||||
cache?: 'default' | 'reload' | 'force-cache' | 'only-if-cached' | undefined;
|
||||
/**
|
||||
|
||||
+1
-1
@@ -66,7 +66,7 @@ export interface ImageURISource {
|
||||
* to a URL load request, no attempt is made to load the data from the originating source,
|
||||
* and the load is considered to have failed.
|
||||
*
|
||||
* @platform ios (for `force-cache` and `only-if-cached`)
|
||||
* @platform ios (for `force-cache`)
|
||||
*/
|
||||
+cache?: ?('default' | 'reload' | 'force-cache' | 'only-if-cached');
|
||||
|
||||
|
||||
@@ -3379,6 +3379,7 @@ public final class com/facebook/react/modules/fresco/FrescoModule$Companion {
|
||||
|
||||
public final class com/facebook/react/modules/fresco/ImageCacheControl : java/lang/Enum {
|
||||
public static final field DEFAULT Lcom/facebook/react/modules/fresco/ImageCacheControl;
|
||||
public static final field ONLY_IF_CACHED Lcom/facebook/react/modules/fresco/ImageCacheControl;
|
||||
public static final field RELOAD Lcom/facebook/react/modules/fresco/ImageCacheControl;
|
||||
public static fun getEntries ()Lkotlin/enums/EnumEntries;
|
||||
public static fun valueOf (Ljava/lang/String;)Lcom/facebook/react/modules/fresco/ImageCacheControl;
|
||||
|
||||
+7
@@ -15,4 +15,11 @@ public enum class ImageCacheControl {
|
||||
* be used to satisfy a URL load request.
|
||||
*/
|
||||
RELOAD,
|
||||
/**
|
||||
* The existing cache data will be used to satisfy a request, regardless of its age or expiration
|
||||
* date. If there is no existing data in the cache corresponding to a URL load request, no attempt
|
||||
* is made to load the data from the originating source, and the load is considered to have
|
||||
* failed.
|
||||
*/
|
||||
ONLY_IF_CACHED,
|
||||
}
|
||||
+3
@@ -43,6 +43,9 @@ internal class ReactOkHttpNetworkFetcher(private val okHttpClient: OkHttpClient)
|
||||
ImageCacheControl.RELOAD -> {
|
||||
cacheControlBuilder.noCache()
|
||||
}
|
||||
ImageCacheControl.ONLY_IF_CACHED -> {
|
||||
cacheControlBuilder.onlyIfCached()
|
||||
}
|
||||
ImageCacheControl.DEFAULT -> {
|
||||
// No-op
|
||||
}
|
||||
|
||||
+11
@@ -41,6 +41,7 @@ import com.facebook.imagepipeline.image.ImageInfo
|
||||
import com.facebook.imagepipeline.postprocessors.IterativeBoxBlurPostProcessor
|
||||
import com.facebook.imagepipeline.request.BasePostprocessor
|
||||
import com.facebook.imagepipeline.request.ImageRequest
|
||||
import com.facebook.imagepipeline.request.ImageRequest.RequestLevel
|
||||
import com.facebook.imagepipeline.request.ImageRequestBuilder
|
||||
import com.facebook.imagepipeline.request.Postprocessor
|
||||
import com.facebook.react.bridge.ReactContext
|
||||
@@ -311,10 +312,18 @@ public class ReactImageView(
|
||||
null,
|
||||
"default" -> ImageCacheControl.DEFAULT
|
||||
"reload" -> ImageCacheControl.RELOAD
|
||||
"only-if-cached" -> ImageCacheControl.ONLY_IF_CACHED
|
||||
else -> ImageCacheControl.DEFAULT
|
||||
}
|
||||
}
|
||||
|
||||
private fun computeRequestLevel(cacheControl: ImageCacheControl): RequestLevel {
|
||||
return when (cacheControl) {
|
||||
ImageCacheControl.ONLY_IF_CACHED -> RequestLevel.DISK_CACHE
|
||||
else -> RequestLevel.FULL_FETCH
|
||||
}
|
||||
}
|
||||
|
||||
public fun setDefaultSource(name: String?) {
|
||||
val newDefaultDrawable = instance.getResourceDrawable(context, name)
|
||||
if (defaultImageDrawable != newDefaultDrawable) {
|
||||
@@ -426,6 +435,7 @@ public class ReactImageView(
|
||||
val imageSource = this.imageSource ?: return
|
||||
val uri = imageSource.uri
|
||||
val cacheControl = imageSource.cacheControl
|
||||
val requestLevel = computeRequestLevel(cacheControl)
|
||||
|
||||
val postprocessorList = mutableListOf<Postprocessor>()
|
||||
iterativeBoxBlurPostProcessor?.let { postprocessorList.add(it) }
|
||||
@@ -445,6 +455,7 @@ public class ReactImageView(
|
||||
.setResizeOptions(resizeOptions)
|
||||
.setAutoRotateEnabled(true)
|
||||
.setProgressiveRenderingEnabled(progressiveRenderingEnabled)
|
||||
.setLowestPermittedRequestLevel(requestLevel)
|
||||
|
||||
if (resizeMethod == ImageResizeMethod.NONE) {
|
||||
imageRequestBuilder.setDownsampleOverride(DownsampleMode.NEVER)
|
||||
|
||||
@@ -659,6 +659,20 @@ function CacheControlAndroidExample(): React.Node {
|
||||
key={reload}
|
||||
/>
|
||||
</View>
|
||||
<View style={styles.leftMargin}>
|
||||
<RNTesterText style={styles.resizeModeText}>
|
||||
Only-if-cached
|
||||
</RNTesterText>
|
||||
<Image
|
||||
source={{
|
||||
uri: fullImage.uri + '?cacheBust=only-if-cached',
|
||||
cache: 'only-if-cached',
|
||||
}}
|
||||
style={styles.base}
|
||||
key={reload}
|
||||
onError={e => console.log(e.nativeEvent.error)}
|
||||
/>
|
||||
</View>
|
||||
</View>
|
||||
|
||||
<View style={styles.horizontal}>
|
||||
@@ -1091,9 +1105,10 @@ exports.examples = [
|
||||
},
|
||||
{
|
||||
title: 'Cache Policy',
|
||||
description: ('First image will be loaded and will be cached. ' +
|
||||
'Second image is the same but will be reloaded if re-rendered ' +
|
||||
'as the cache policy is set to reload.': string),
|
||||
description: `- First image will be loaded and cached.
|
||||
- Second image is the same but will be reloaded if re-rendered as the cache policy is set to reload.
|
||||
- Third image will never be loaded as the cache policy is set to only-if-cached and the image has not been loaded before.
|
||||
`,
|
||||
render: function (): React.Node {
|
||||
return <CacheControlAndroidExample />;
|
||||
},
|
||||
|
||||
Reference in new issue
Block a user