如何获取未缓存在 android 线圈中的新图像?

How can I get a new image not cached in android coil?

我正在使用 Jetpack Compose 和 Coil ImageLoader 库开发 android 应用程序。

显示用户的个人资料图片。

我从 API 收到配置文件数据。 GET: /users/{userId}

响应包含 userIdprofileImgKey

对于用户头像,后端提供GET: /photo/{userId}API。

但问题是,如果某些用户更新 his/her 个人资料图片,其他用户仍然看到以前的个人资料图片,而不是新图片。

因为被Coil缓存了。

如果我关闭缓存选项,它可能会正常工作。 但我不想这样做。 我不想失去性能优势。

当用户更新他们的个人资料图片时,profileImgKey 会更改。 所以我想用它作为缓存键。

但是我不知道怎么用

在 Coil 2.0.0 中,网络缓存的使用得到了显着简化。

rememberAsyncImagePainter中指定diskCacheKeymemoryCacheKey,并且仍然需要key来触发重组。

val context = LocalContext.current
key(key) {
    Image(
        rememberAsyncImagePainter(
            remember(url) {
                ImageRequest.Builder(context)
                    .data(url)
                    .diskCacheKey(url)
                    .memoryCacheKey(url)
                    .build()
            }
        ),
        null
    )
}

并使用图片加载器清除缓存:

val imageLoader = context.imageLoader
imageLoader.diskCache?.remove(url)
imageLoader.memoryCache?.remove(MemoryCache.Key(url))

线圈的答案 1.4.0

Coil 有两个级别的缓存:

  1. 对于网络调用,Coil 使用 OkHttp,要访问其缓存,您需要手动创建它,如 documentation 所示。我认为在这种情况下,最好将缓存和图像加载器都存储在 DI 中,但您也可以创建一个本地组合以从任何可组合项访问此缓存:

    val LocalCoilHttpCache = staticCompositionLocalOf<Cache> {
        error("coilHttpCache not provided")
    }
    

    在您的activity/fragment中提供:

    val cache = CoilUtils.createDefaultCache(this)
    val imageLoader = ImageLoader.Builder(this)
        .okHttpClient {
            OkHttpClient.Builder()
                .cache(cache)
                .build()
        }
        .build()
    
    setContent {
        CompositionLocalProvider(
            LocalImageLoader provides imageLoader,
            LocalCoilHttpCache provides cache,
        ) {
            // your application
        }
    }
    

    在任何可组合项中获取它

    val httpCache = LocalCoilHttpCache.current
    

    然后,不管你存放在DI的什么地方,还是存放在合成本地,都可以用下面的代码清除必要的缓存:

    val urlIterator = httpCache.urls()
    while (urlIterator.hasNext()) {
        if (urlIterator.next() == urlToRemove) {
            urlIterator.remove()
        }
    }
    
  2. 从网络下载图片后,转换为Bitmap。这些位图使用 Memory cache 缓存,因此您也需要清除它。根据文档,最简单的方法是指定缓存键,例如URL:

    rememberImagePainter(
        url,
        builder = {
            memoryCacheKey(MemoryCache.Key(url))
        }
    ),
    

    然后就可以清理了:

    val loader = LocalImageLoader.current
    // or out of composable
    val loader = Coil.imageLoader(context)
    // ..
    loader.memoryCache.remove(MemoryCache.Key(url))
    

最后一步是强制图像重组。您可以使用 key 执行此操作,指定要更改的值,在您的情况下 profileImgKey 应该有效:

key(profileImgKey) {
    Image(
        rememberImagePainter(
            // ...

即使图像发生变化也能确保您获得新鲜图像的最简单方法是使用随机值将查询参数附加到 url。例如:

someurl/user1.jpg?49610269

然后这样做:

val imageUrl = "someUrl/user1.jpg?" + (0..1_000_000).random()

如果您的 url 已经有查询参数,只需添加一个您的 url 不使用的新参数。

只要url(包括查询字符串)不改变,就会重复使用缓存中的图像。通过更改 url,您可以强制 Coil 获取最新图像。