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

yoo*_*hok 7 android android-jetpack-compose coil

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

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

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

响应包含userIdprofileImgKey

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

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

因为它是被Coil缓存的。

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

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

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

Phi*_*hov 13

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

仍然需要指定diskCacheKeymemoryCacheKey来触发重组。rememberAsyncImagePainterkey

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

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

val imageLoader = context.imageLoader
imageLoader.diskCache?.remove(url)
imageLoader.memoryCache?.remove(MemoryCache.Key(url))
Run Code Online (Sandbox Code Playgroud)

线圈1.4.0的答案

Coil 有两个级别的缓存:

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

    val LocalCoilHttpCache = staticCompositionLocalOf<Cache> {
        error("coilHttpCache not provided")
    }
    
    Run Code Online (Sandbox Code Playgroud)

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

    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
        }
    }
    
    Run Code Online (Sandbox Code Playgroud)

    在任何可组合项中获取它

    val httpCache = LocalCoilHttpCache.current
    
    Run Code Online (Sandbox Code Playgroud)

    然后,无论您将其存储在 DI 中还是组合本地中的哪个位置,都可以使用以下代码清除必要的缓存:

    val urlIterator = httpCache.urls()
    while (urlIterator.hasNext()) {
        if (urlIterator.next() == urlToRemove) {
            urlIterator.remove()
        }
    }
    
    Run Code Online (Sandbox Code Playgroud)
  2. 从网络下载图像后,将其转换为Bitmap. 这些位图通过Memory cache进行缓存,因此您也需要清除它。根据文档,最简单的方法是指定一个缓存键,例如 URL:

    rememberImagePainter(
        url,
        builder = {
            memoryCacheKey(MemoryCache.Key(url))
        }
    ),
    
    Run Code Online (Sandbox Code Playgroud)

    然后你可以清理它:

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

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

key(profileImgKey) {
    Image(
        rememberImagePainter(
            // ...
Run Code Online (Sandbox Code Playgroud)