diff --git a/coil-core/src/androidMain/kotlin/coil3/RealImageLoader.android.kt b/coil-core/src/androidMain/kotlin/coil3/RealImageLoader.android.kt index d0fdfe0ff9..d5f12295ce 100644 --- a/coil-core/src/androidMain/kotlin/coil3/RealImageLoader.android.kt +++ b/coil-core/src/androidMain/kotlin/coil3/RealImageLoader.android.kt @@ -1,5 +1,7 @@ package coil3 +import android.graphics.Bitmap +import android.graphics.drawable.Drawable import android.os.Build.VERSION.SDK_INT import coil3.decode.BitmapFactoryDecoder import coil3.decode.ExifOrientationStrategy.Companion.RESPECT_ALL @@ -11,6 +13,7 @@ import coil3.fetch.ContentUriFetcher import coil3.fetch.DrawableFetcher import coil3.fetch.ResourceUriFetcher import coil3.key.AndroidResourceUriKeyer +import coil3.key.CacheDisabledKeyer import coil3.map.AndroidUriMapper import coil3.map.ResourceIntMapper import coil3.request.Disposable @@ -79,6 +82,10 @@ internal actual fun ComponentRegistry.Builder.addAndroidComponents( // Keyers add(AndroidResourceUriKeyer()) + if (options.defaultKeyerEnabled) { + add(CacheDisabledKeyer()) + add(CacheDisabledKeyer()) + } // Fetchers add(AssetUriFetcher.Factory()) diff --git a/coil-core/src/commonMain/kotlin/coil3/RealImageLoader.kt b/coil-core/src/commonMain/kotlin/coil3/RealImageLoader.kt index 8be04286b2..cd3009adca 100644 --- a/coil-core/src/commonMain/kotlin/coil3/RealImageLoader.kt +++ b/coil-core/src/commonMain/kotlin/coil3/RealImageLoader.kt @@ -6,6 +6,7 @@ import coil3.fetch.DataUriFetcher import coil3.fetch.FileUriFetcher import coil3.intercept.EngineInterceptor import coil3.intercept.RealInterceptorChain +import coil3.key.CacheEnabledKeyer import coil3.key.FileUriKeyer import coil3.key.UriKeyer import coil3.map.PathMapper @@ -56,7 +57,7 @@ internal class RealImageLoader( .addAndroidComponents(options) .addJvmComponents(options) .addAppleComponents(options) - .addCommonComponents() + .addCommonComponents(options) .add(EngineInterceptor(this, systemCallbacks, requestService, options.logger)) .build() private val shutdown = atomic(false) @@ -288,18 +289,24 @@ internal expect fun ComponentRegistry.Builder.addAppleComponents( options: RealImageLoader.Options, ): ComponentRegistry.Builder -internal fun ComponentRegistry.Builder.addCommonComponents(): ComponentRegistry.Builder { - return this - // Mappers - .add(StringMapper()) - .add(PathMapper()) - // Keyers - .add(FileUriKeyer()) - .add(UriKeyer()) - // Fetchers - .add(FileUriFetcher.Factory()) - .add(ByteArrayFetcher.Factory()) - .add(DataUriFetcher.Factory()) +internal fun ComponentRegistry.Builder.addCommonComponents( + options: RealImageLoader.Options, +): ComponentRegistry.Builder = apply { + // Mappers + add(StringMapper()) + add(PathMapper()) + + // Keyers + add(FileUriKeyer()) + add(UriKeyer()) + if (options.defaultKeyerEnabled) { + add(CacheEnabledKeyer()) + } + + // Fetchers + add(FileUriFetcher.Factory()) + add(ByteArrayFetcher.Factory()) + add(DataUriFetcher.Factory()) } private const val TAG = "RealImageLoader" diff --git a/coil-core/src/commonMain/kotlin/coil3/imageLoaders.kt b/coil-core/src/commonMain/kotlin/coil3/imageLoaders.kt index 7410398896..b3aa6d71d3 100644 --- a/coil-core/src/commonMain/kotlin/coil3/imageLoaders.kt +++ b/coil-core/src/commonMain/kotlin/coil3/imageLoaders.kt @@ -1,5 +1,7 @@ package coil3 +import coil3.key.Keyer + /** * Create a new [ImageLoader] without configuration. */ @@ -30,3 +32,19 @@ internal val RealImageLoader.Options.serviceLoaderEnabled: Boolean private val serviceLoaderEnabledKey = Extras.Key(default = true) // endregion + +/** + * Enables the default [Keyer]. This means that data types that don't have a registered [Keyer] + * will have a memory cache key created for them using [Any.toString]. + * + * If disabled (the default), images will not be cached if they do not have a registered [Keyer] + * for the associated data type. + */ +fun ImageLoader.Builder.defaultKeyerEnabled(enable: Boolean) = apply { + extras[defaultKeyerEnabledKey] = enable +} + +internal val RealImageLoader.Options.defaultKeyerEnabled: Boolean + get() = defaults.extras.getOrDefault(defaultKeyerEnabledKey) + +private val defaultKeyerEnabledKey = Extras.Key(default = false) diff --git a/coil-core/src/commonMain/kotlin/coil3/key/AnyKeyer.kt b/coil-core/src/commonMain/kotlin/coil3/key/AnyKeyer.kt new file mode 100644 index 0000000000..03ef591887 --- /dev/null +++ b/coil-core/src/commonMain/kotlin/coil3/key/AnyKeyer.kt @@ -0,0 +1,21 @@ +package coil3.key + +import coil3.request.Options + +@Suppress("UNCHECKED_CAST") +internal fun CacheEnabledKeyer(): Keyer = CacheEnabledKeyer as Keyer + +private object CacheEnabledKeyer : Keyer { + override fun key(data: Any, options: Options): String { + return data.toString() + } +} + +@Suppress("UNCHECKED_CAST") +internal fun CacheDisabledKeyer(): Keyer = CacheDisabledKeyer as Keyer + +private object CacheDisabledKeyer : Keyer { + override fun key(data: Any, options: Options): String? { + return null + } +}