1

我正在使用带有 Coil ImageLoader 库的 Jetpack Compose 开发一个 android 应用程序。

它显示用户的个人资料图像。

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

响应包含userIdprofileImgKey

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

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

因为它是由 Coil 缓存的。

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

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

但我不知道如何使用这个。

4

2 回答 2

1

在 Coil 2.0.0中,网络缓存的使用得到了显着简化,但尚未发布 - 目前的最新版本是2.0.0-alpha08

指定diskCacheKeymemoryCacheKeyrememberAsyncImagePainterkey仍然需要触发重组。

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的答案

线圈有两个级别的缓存:

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

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

    在您的活动/片段中提供它:

    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(
            // ...
于 2022-02-15T05:14:36.620 回答
0

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

someurl/user1.jpg?49610269

并这样做:

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

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

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

于 2022-02-15T05:21:42.460 回答