0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【Jetpack Compose】coilで表示前に画像のキャッシュを作成する

Last updated at Posted at 2025-10-28

AsyncImageにplaceHolderを表示したくない

 画面遷移後にサーバから受け取った画像を表示したかった...のですが、AsyncImageにURLを丸投げすると、画像の読み込み中は何も表示されず、後から画像が反映されてしまいます。
 もちろんplaceHolderを指定することもできますが、UI次第では後から画像が反映されると気持ち悪かったりするので、APIから画像のURLを取得 -> coilで画像のキャッシュを作成 -> 完了次第UIを表示という順で表示する方法で実装しました。

実装

 coil-composeのバージョンは2.2.2です。

interface ImageCacheRepository {
   suspend fun loadCache(urlList: List<String>)
}

class DefaultImageCacheRepository(
   private val context: Context,
   private val dispatcher: CoroutineDispatcher = Dispatchers.IO,
) : ImageCacheRepository {
   override suspend fun loadCache(urlList: List<String>) {
       withContext(dispatcher) {
           val jobs = urlList.map { imageUrl ->
               async {
                   val request = ImageRequest.Builder(context)
                       .data(imageUrl)
                       .allowHardware(false)
                       .size(Size.ORIGINAL)
                       .build()
                   context.imageLoader.enqueue(request)
               }
           }
           jobs.awaitAll()
       }
   }
}

 imageLoader.enqueue()を実行するとBitmapの作成を並列でやってくれます。(imageLoader.execute()だとスレッドを止めるので注意。)
 あとはこのリポジトリにapplicationContextを入れて、サーバから受け取ったURLのリストをloadCache()に渡し、loadCache()の実行完了後にUIが描画されるように実装すればOK。AsyncImageにキャッシュを作成したURLを渡せば通信を挟むことなく表示してくれます。
 一応、並列でリクエストを送るので、あまりにも要素数の多いリストを渡すとサーバに負荷をかける可能性があります。

キャッシュについて

 coilのImageLoaderはデフォルトでメモリとディスクの両方にキャッシュを作成します。

DefaultRequestOptions.kt
class DefaultRequestOptions(
    val interceptorDispatcher: CoroutineDispatcher = Dispatchers.Main.immediate,
    val fetcherDispatcher: CoroutineDispatcher = Dispatchers.IO,
    val decoderDispatcher: CoroutineDispatcher = Dispatchers.IO,
    val transformationDispatcher: CoroutineDispatcher = Dispatchers.IO,
    val transitionFactory: Transition.Factory = Transition.Factory.NONE,
    val precision: Precision = Precision.AUTOMATIC,
    val bitmapConfig: Bitmap.Config = DEFAULT_BITMAP_CONFIG,
    val allowHardware: Boolean = true,
    val allowRgb565: Boolean = false,
    val placeholder: Drawable? = null,
    val error: Drawable? = null,
    val fallback: Drawable? = null,
    val memoryCachePolicy: CachePolicy = CachePolicy.ENABLED,
    val diskCachePolicy: CachePolicy = CachePolicy.ENABLED,
    val networkCachePolicy: CachePolicy = CachePolicy.ENABLED,
)

こちらは用途に応じて .diskCachePolicy(CachePolicy.DISABLED)を追加してディスクキャッシュを作成しないようにしたり、不要になった時点でcontext.imageLoader.memoryCache?.clear()でメモリキャッシュを削除したりしても良いかもしれません。

参考

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?