Jetpack Compose 中的 Coil 图像缓存无法正常工作。

5

我正在使用coil(version 2.1.0)从URL加载图片。当有网络连接时,图片可以正常加载。然而,在没有网络连接时,图片并没有像我预期的那样从缓存中获取。这是我的一段代码:

class App : Application(), ImageLoaderFactory {

    override fun newImageLoader(): ImageLoader {
       return ImageLoader.Builder(this)
            .memoryCache {
                MemoryCache.Builder(this)
                    .maxSizePercent(0.25)
                    .build()
            }
            .diskCache {
                DiskCache.Builder()
                    .directory(cacheDir.resolve("image_cache"))
                    .maxSizeBytes(5 * 1024 * 1024)
                    .build()
            }
            .build()
    }
  }


在Compose中:
                val context = LocalContext.current
                val placeholderImage = R.drawable.ic_placeholder
    
                val imageRequest = ImageRequest.Builder(context)
                    .data(imageUrl)
                    .memoryCacheKey(imageUrl)
                    .diskCacheKey(imageUrl)
                    .placeholder(placeholderImage)
                    .error(placeholderImage)
                    .fallback(placeholderImage)
                    .diskCachePolicy(CachePolicy.ENABLED)
                    .memoryCachePolicy(CachePolicy.ENABLED)
                    .transformations(CircleCropTransformation())
                    .build()

                AsyncImage(
                    model = imageRequest,
                    modifier = Modifier.size(64.dp),
                    contentDescription = null,
                    imageLoader = context.imageLoader
                )

当设备离线时,它只加载占位图像,而不像预期那样从缓存中加载图像。我错过了什么?


不要使用cacheDir.resolve,而是使用filesDir.resolve。请查看此问题的更多信息:https://github.com/coil-kt/coil/issues/1447 - undefined
2个回答

12
我在ImageLoader中使用logger(DebugLogger())来找出问题所在,发现当Coil尝试离线加载图像时,应用程序遇到了HTTP 504错误。因此,我向ImageLoader添加了.respectCacheHeaders(false)。这对我来说似乎解决了问题。
希望这能帮助其他遇到类似问题的人。

这个在代码中是什么样子? - IgorGanapolsky
2
@IgorGanapolsky val imageLoader = ImageLoader.Builder(context).components { add(ImageDecoderDecoder.Factory()) }.respectCacheHeaders(false).build() 然后像这样将其传递给图像 Image(painter = rememberAsyncImagePainter(imageRequest, imageLoader = imageLoader), contentDescription = null) - yuroyami

1

Coil将根据HTTP头中的Cache-Control字段来决定是否需要磁盘缓存。

以下是Coil 2.0.0的变更日志。

  • 新增:引入公共DiskCache API。
    • 使用ImageLoader.Builder.diskCacheDiskCache.Builder配置磁盘缓存。
    • 不应在Coil 2.0中使用OkHttp的Cache。有关更多信息,请参见这里
    • Cache-Control和其他缓存头仍受支持,但Vary头不受支持,因为缓存只检查URL是否匹配。 此外,只有响应代码在[200..300)范围内的响应才会被缓存。
    • 升级到2.0时现有的磁盘缓存将被清除。

如果您需要强制缓存,请参见https://coil-kt.github.io/coil/recipes/#headers。我认为最好使用addHeader以避免丢弃其他HTTP头字段。


1
我不认为是这样的。变更日志显示缓存标头仍然受支持,它并没有说自动缓存将被取消。如果该库强制用户在HTTP级别上添加标头来使用其核心功能,那将非常愚蠢,我认为。 - Jakoss
我同意对于coil2.0来说,这样的api很奇怪,但至少在我的项目中我需要缓存控制字段。 - FishHawk
也许这只是一个错误,因为在官方缓存文档 https://coil-kt.github.io/coil/image_loaders/#caching 中,并没有提到需要缓存控制头。 - Jakoss
我记得在2.0之前,这个页面没有提到这一点。我不认为这是一个bug。尊重http头部是一个合理的设计。也许Coil最好为addHeader("Cache-Control", ...) 提供一个别名。无论如何,至少你可以尝试一下看看它是否有效。 - FishHawk
随着2.x版本的到来,因为Coil已经实现了自己的磁盘缓存机制,所以OkHttp的缓存将不再被Coil使用。https://coil-kt.github.io/coil/upgrading/#disk-cache针对我的问题,我找到了一个解决方法,并已在下面发布为答案。 - lokesh

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接