Coil — その概要、主要概念、AndroidでのImageLoader

著者: IT Sectr 公開日: 2026-05-05 読了時間: 9 分

Coilは、Kotlinで書かれ、コルーチンをベースにしたAndroid用画像読み込みライブラリです。公式ドキュメントによると、このライブラリはMemory Cache、Disk Cache、ハードウェアアクセラレーションによる変換をサポートしています。Coilは、最小限のAPKサイズ(約150KB)とJetpack Composeとの完全な互換性で際立っています。

重要なポイント

  • Coilは、Android用の画像読み込みライブラリで、Kotlin CoroutinesとKotlin Serializationを使用します。
  • ImageLoaderは、リクエスト、キャッシング、画像変換を管理する中心的なコンポーネントです。
  • Memory Cacheは、デコードされたビットマップ画像をRAMに保存し、瞬時にアクセスできるようにします。
  • Disk Cacheは、オフライン作業とトラフィック削減のために、圧縮ファイルをストレージに保存します。
  • Jetpack Compose — ライブラリは宣言的UIのためのAsyncImageとSubcomposeAsyncImageをサポートしています。

Coilとは?

Coil(Coroutine Image Loader)は、完全にKotlinで書かれ、非同期操作にコルーチンを使用するAndroid用画像読み込みライブラリです。ネットワーク、リソース、ファイルシステム、Content Providerからビットマップ画像を読み込むための統一APIを提供し、自動マルチレベルキャッシングを備えています。

GlideやPicassoとは異なり、Coilはコールバックチェーンの代わりにKotlin Coroutinesを使用するため、コードがより直線的で予測可能になります。すべての読み込みとデコード操作は、Dispatchers.IOディスパッチャーを介してバックグラウンドスレッドで実行され、結果は明示的な切り替えなしにメインスレッドに配信されます。

Coilは変換(Round、Blur、Grayscale)、トランジションアニメーション、SVG、GIF、および非標準表示用のカスタムTargetをサポートしています。Google I/O 2023によると、CoilはGlideと並んで公式のJetpack Composeチュートリアルで推奨されています。

  • APKサイズ — 約150KB(Glideの500KBに対して)
  • 最小Androidバージョン — API 21(Lollipop)
  • 依存関係 — Kotlin Coroutines(組み込み)

Coilの仕組み:ImageLoaderとImageRequest

ImageLoaderはCoilの主要コンポーネントで、読み込みリクエストの実行とキャッシュの管理を担当します。各インスタンスは、MemoryCache、DiskCache、BitmapPool、およびコルーチンプールへの参照を保持します。デフォルトでは、Coil.imageLoader(context)を介して作成されたシングルトンが使用されます。

ImageRequest

ImageRequestは、単一の画像読み込みリクエストを記述するオブジェクトです:データソース(URL、URI、Intリソース)、ターゲットのImageViewまたはTarget、変換、キャッシュ設定、プレースホルダー。ImageRequestはビルダーを介して構築され、柔軟性と可読性を確保します。

kotlin
val request = ImageRequest.Builder(context)
    .data("https://example.com/image.jpg")
    .crossfade(true)
    .size(512, 512)
    .transformations(listOf(RoundedCornersTransformation(12f)))
    .memoryCachePolicy(CachePolicy.ENABLED)
    .diskCachePolicy(CachePolicy.ENABLED)
    .target(imageView)
    .build()

構築後、ImageRequestはenqueueまたはexecuteを介してImageLoaderに渡されます。enqueueメソッドはコルーチンを起動し、Disposableを返します。これにより、画面を離れるときに読み込みをキャンセルできます。executeメソッドはサスペンド関数で、Resultを直接返します。

リクエスト実行フロー

ImageLoaderは、MemoryCache、DiskCacheを順次チェックし、両方でミスした場合にのみHttpEngineを介してネットワークリクエストを実行します。読み込み後、バイトはターゲットサイズを考慮してBitmapにデコードされ、変換が適用され、結果は両方のキャッシュに保存されてTargetに渡されます。

  • Memory Cache — 最初にチェック、キーはURL + パラメータ
  • Disk Cache — メモリミス時にチェック、キーはURLのMD5
  • HttpEngine — デフォルトはOkHttp、コンポーネントを介してカスタマイズ可能

Coilの主要コンポーネント

Coilはコンポーネントアーキテクチャに基づいて構築されており、依存性注入を介して任意の部分を置き換えることができます。すべてのコンポーネントはImageLoaderFactoryに登録され、ビルダーを介してImageLoaderコンストラクタに渡されます。

ImageLoader

ImageLoaderは、すべての読み込み操作のエントリポイントです。各インスタンスには、コルーチンプール、BitmapPool、MemoryCache、DiskCache、およびインターセプターのリストが含まれています。デフォルトでは1つのグローバルインスタンスが作成されますが、単体テスト用に、分離されたキャッシュを持つ個別のインスタンスを作成できます。

MemoryCache

MemoryCacheは、LRU(Least Recently Used)ベースのインメモリキャッシュで、デコードされたBitmapオブジェクトを保存します。デフォルトの最大サイズは、利用可能なアプリケーションメモリの25%ですが、32 MBを下回ることはありません。キャッシュキーはURL + サイズ + 変換から形成され、古い画像の取得を防ぎます。

DiskCache

DiskCacheは、生データ(JPEG、PNG、WebP)とデコードされたメタデータ用のファイルベースのキャッシュです。アプリケーションのキャッシュディレクトリに配置され、制限を超えると自動クリーンアップをサポートします。ディスク操作は、ディレクトリと最大サイズの設定を備えたDiskCache.Builderを介して実行されます。

Coilのキャッシュレベル

Coilは、ネットワークリクエストを最小限に抑え、画像表示を高速化するマルチレベルキャッシュ戦略を実装しています。各レベルには独自の目的とデータライフタイムがあります。

レベルストレージタイプライフタイムデフォルトサイズ
Memory CacheRAM内のBitmapLRU退避までヒープの25%、32 MBから
Disk CacheJPEG/WebPファイル制限超過まで250 MB
Http CacheOkHttp応答Cache-Controlヘッダーに従うHTTPクライアントに依存

Memory Cacheは、すでにデコードされたBitmapへの瞬時アクセスを提供します。Disk Cacheは、初回読み込み後にネットワークなし(オフラインファースト)でのアプリケーション動作を保証します。OkHttpレベルのHttp Cacheは、ETagおよびIf-Modified-Sinceによる条件付きリクエストを処理します。

キャッシュポリシーは、CachePolicyを介してリクエストごとに設定されます。値はENABLED、READ_ONLY、WRITE_ONLY、DISABLEDの3つです。たとえば、ユーザーアバターの場合、Memory CacheにREAD_ONLY、Disk CacheにENABLEDを設定できます。

KotlinでのCoil使用例

Coilは、アプリケーションアーキテクチャに応じて複数の統合方法を提供します。実際のコード例を使って、3つの主要なシナリオを見てみましょう。

拡張関数によるImageViewへの読み込み

loadはImageViewの拡張関数で、1行で画像を読み込む最も簡単な方法です。この関数は、URL、URI、Intリソース、またはFileと、ラムダコンフィギュレーターを介したすべてのオプションパラメータを受け入れます。

kotlin
imageView.load("https://example.com/photo.jpg") {
    crossfade(true)
    placeholder(R.drawable.placeholder)
    error(R.drawable.error)
    size(300, 300)
    transformations(CircleCropTransformation())
}

loadメソッドはDisposableを返します。これはonDestroyまたはViewの再利用時にキャンセルできます。これにより、高速なリストスクロール時のメモリリークと不要なネットワークリクエストを防ぎます。

Jetpack Composeでの使用

AsyncImageは、宣言的UIで画像を読み込むためのコンポーザブル関数です。任意のデータソースと、プレースホルダー、エラー、サクセスの3つのオプションの状態パラメータを受け入れます。

kotlin
@Composable
fun NetworkImage(url: String) {
    AsyncImage(
        model = url,
        contentDescription = "ネットワーク画像",
        placeholder = ColorPainter(Color.Gray),
        error = ColorPainter(Color.Red)
    )
}

SubcomposeAsyncImageはより柔軟なバージョンで、コンテンツスロットを通じて読み込み中の表示をカスタマイズできます。これはスケルトン(shimmer)やプログレスバーに便利です。

非標準出力のためのカスタムTarget

ImageViewやAsyncImageが適さない場合は、Bitmapを受け取る単一のonSuccessメソッドを持つTargetを実装できます。これはNotification、RemoteViews、OpenGLテクスチャへの読み込みに使用されます。

kotlin
val target = object : BitmapTarget() {
    override fun onSuccess(result: Bitmap) {
        notificationRemoteView.setImageViewBitmap(R.id.icon, result)
    }
}

imageLoader.enqueue(
    ImageRequest.Builder(context)
        .data(url)
        .target(target)
        .build()
)

他のライブラリとの比較

画像読み込みライブラリの選択はプロジェクトの要件によって異なります。CoilはGlideやPicassoと競合しており、それぞれに強みがあります。主要な特性の比較を表に示します。

特性CoilGlidePicasso
言語Kotlin(100%)Java + KotlinJava
APKサイズ~150 KB~500 KB~120 KB
コルーチン組み込みなし(コールバック)なし(コールバック)
Jetpack Composeネイティブサポートaccompanist経由サードパーティ
GIF/WebPはい(組み込み)はい(組み込み)いいえ
Google推薦はい(I/O 2023)はいいいえ

KotlinとJetpack Composeの新しいプロジェクトでは、追加のコルーチン依存関係がゼロでサイズが最小のCoilが自然な選択肢になります。Glideはアニメーションやビデオプレビューを伴う複雑なシナリオで引き続き好まれます。Picassoは機能面で両者に劣りますが、シンプルさでは勝っています。

AndroidプロジェクトでのCoil設定

AndroidプロジェクトへのCoilの追加は、Gradle依存関係を介して行います。追加後、ライブラリはContentProviderを介して自動的にImageLoaderを登録するため、Applicationでの手動初期化は不要です。カスタマイズが必要な場合は、ビルダーを介してカスタムImageLoaderを作成します。

kotlin
// build.gradle.kts(app module)
dependencies {
    implementation("io.coil-kt:coil:2.6.0")
    // Jetpack Composeの場合はさらに:
    implementation("io.coil-kt:coil-compose:2.6.0")
    // SVGサポートの場合:
    implementation("io.coil-kt:coil-svg:2.6.0")
    // GIFサポートの場合:
    implementation("io.coil-kt:coil-gif:2.6.0")
}

ImageLoaderをカスタマイズするには、ImageLoaderFactoryを使用します — Application.onCreateで作成されるシングルトンです。ファクトリでは、キャッシュ制限、HTTPクライアント、カスタムデコーダー、ロギングを設定できます。デフォルトでは、Coilは準備済みの接続プールを持つOkHttpを使用します。

kotlin
class App : Application(), ImageLoaderFactory {
    override fun newImageLoader(): ImageLoader {
        return ImageLoader.Builder(this)
            .memoryCache {
                MemoryCache.Builder()
                    .maxSizePercent(0.25)
                    .build()
            }
            .diskCache {
                DiskCache.Builder()
                    .directory(cacheDir.resolve("coil_cache"))
                    .maxSizeBytes(512 * 1024 * 1024)
                    .build()
            }
            .build()
    }
}

よくある質問

Coilとは何で、何に使用されますか?

Coilは、Kotlinでコルーチンを使用して書かれたAndroid用画像読み込みライブラリです。ネットワーク、リソース、ファイルシステムからのビットマップ画像の非同期読み込み、キャッシング、表示に使用されます。

CoilはGlideとどう違いますか?

Coilは100%Kotlinで書かれており、Glideのコールバック機構の代わりにコルーチンを使用します。CoilはAPKサイズが小さく(〜150KB vs 〜500KB)、AsyncImageを介したJetpack Composeのネイティブサポートを備えています。

KotlinプロジェクトにCoilを追加するには?

依存関係io.coil-kt:coil:2.6.0をbuild.gradle.ktsに追加します。Jetpack Composeの場合は、io.coil-kt:coil-compose:2.6.0も追加します。ライブラリはContentProviderを介して自動的にImageLoaderを登録します。

Coilはどの画像形式をサポートしていますか?

CoilはJPEG、PNG、WebP、BMP、SVG(coil-svgモジュール経由)、GIF(coil-gifモジュール経由)をサポートしています。AVIFとHEIF形式は、Android 10+のデバイスでカスタムデコーダーを介してサポートされています。

Coilでキャッシュを設定するには?

キャッシュはImageLoader.Builderを介して設定します:memoryCacheはヒープの割合、diskCacheはパスとバイト単位の制限を指定します。キャッシュポリシー(ENABLED、DISABLED、READ_ONLY)はCachePolicyを介してリクエストごとに設定します。

まとめ

  • Coilは、完全なコルーチンとJetpack Composeのサポートを備えたKotlin用画像読み込みライブラリです。
  • ImageLoaderは、Memory CacheとDisk Cacheの2つのキャッシュレベルを使用して、リクエスト、キャッシング、変換を管理します。
  • AsyncImageSubcomposeAsyncImageは、プレースホルダー、エラー、サクセス状態をサポートするCompose統合を提供します。
  • APKサイズ ~150KBにより、Coilは市場で最もコンパクトな画像読み込みライブラリの1つです。
  • 変換(RoundedCorners、CircleCrop、Blur)はライブラリに組み込まれており、ハードウェアアクセラレーションで動作します。
  • Disk Cacheは、設定可能なストレージ制限で、以前に読み込まれた画像へのオフラインアクセスを提供します。
  • CoilはGoogle推奨の公式Jetpack Composeガイドに記載されており、現代の標準としての地位を確認しています。

ターンキー方式のモバイルアプリケーションを開発します

IT Sectrは2017年からスタートアップや企業向けにiOS・Androidアプリケーションを開発しています。私たちがご相談に乗り、最適なソリューションをご提案します。

プロジェクトについて相談

こちらもお読みください