5

I am using coil(version 2.1.0) to load images from URL. When there is network connection, the images are loading fine. However, when there is no network connection, the images are not being pulled from the cache as I expected them. Here's a block of code I have.

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()
    }
  }

In 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
                )

When the device is offline, it only loads the placeholder image instead of the image from cache as expected. What am I missing here?

lokesh
  • 601
  • 7
  • 19

2 Answers2

8

I used logger(DebugLogger()) in ImageLoader to figure out what was going on and I found out that app was running into HTTP 504 error when Coil was trying to load image offline. So I added .respectCacheHeaders(false) to the ImageLoader. That seemed to do the trick for me.

Hope this helps someone else running into similar problem.

lokesh
  • 601
  • 7
  • 19
  • What does this look like in code? – IgorGanapolsky Jan 16 '23 at 00:43
  • 1
    @IgorGanapolsky ```val imageLoader = ImageLoader.Builder(context).components { add(ImageDecoderDecoder.Factory()) }.respectCacheHeaders(false).build()``` then pass it to an Image like this ```Image(painter = rememberAsyncImagePainter(imageRequest, imageLoader = imageLoader), contentDescription = null)``` – yuroyami Apr 03 '23 at 03:40
1

coil will decide if disk caching is required based on the Cache-Control field in the http header.

Here is the change log of coil 2.0.0.

  • New: Introduce a public DiskCache API.
    • Use ImageLoader.Builder.diskCache and DiskCache.Builder to configure the disk cache.
    • You should not use OkHttp's Cache with Coil 2.0. See here for more info.
    • Cache-Control and other cache headers are still supported - except Vary headers, as the cache only checks that the URLs match. Additionally, only responses with a response code in the range [200..300) are cached.
    • Existing disk caches will be cleared when upgrading to 2.0.

If you need to force caching, see https://coil-kt.github.io/coil/recipes/#headers. And I think it would be better to use addHeader to avoid dropping other http header fields.

FishHawk
  • 414
  • 4
  • 11
  • 1
    I don't think that's the case. The change log says that cache headers are still supported, it doesn't say the automatic caching without it is being dumped. That would be really stupid imo if the library forced user to add headers on http level to use its core functionality – Jakoss Jul 15 '22 at 06:02
  • I agree that for coil2.0. such an api is strange, but at least in my project I need the cache control field. – FishHawk Jul 15 '22 at 06:10
  • Maybe it's just a bug since on official cache docs: https://coil-kt.github.io/coil/image_loaders/#caching there is nothing about cache-control headers requirement – Jakoss Jul 15 '22 at 06:53
  • I remember before 2.0, this page didn't mention this. I don't think it's a bug. Respecting the http header is a reasonable design. Perhaps it would be better for Coil to provide an alias for `addHeader("Cache-Control", ...) `. Anyway, at least you can try it to see if it works. – FishHawk Jul 15 '22 at 07:07
  • With 2.x, OkHttp's cache will not be used by Coil since it implements its own disk cache. https://coil-kt.github.io/coil/upgrading/#disk-cache I found a workaround for my case, which I have posted below as an answer. – lokesh Jul 15 '22 at 17:57