Coil — cosa sono, concetti chiave e ImageLoader in Android

Autore: IT Sectr Pubblicato: 2026-05-05 Tempo di lettura: 9 min

Coil è una libreria per il caricamento di immagini su Android, scritta in Kotlin e basata su coroutine. Secondo la documentazione ufficiale, la libreria supporta Memory Cache, Disk Cache e trasformazioni con accelerazione hardware. Coil si distingue per le dimensioni minime dell'APK (circa 150 KB) e la piena compatibilità con Jetpack Compose.

Punti chiave

  • Coil è una libreria per il caricamento di immagini su Android che utilizza Kotlin Coroutines e Kotlin Serialization.
  • ImageLoader è il componente centrale che gestisce le richieste, la memorizzazione nella cache e le trasformazioni delle immagini.
  • Memory Cache memorizza le immagini bitmap decodificate nella RAM per un accesso istantaneo.
  • Disk Cache salva i file compressi sull'archiviazione per il lavoro offline e la riduzione del traffico.
  • Jetpack Compose — la libreria supporta AsyncImage e SubcomposeAsyncImage per UI dichiarativa.

Cos'è Coil?

Coil (Coroutine Image Loader) è una libreria per il caricamento di immagini su Android, interamente scritta in Kotlin e che utilizza coroutine per operazioni asincrone. Fornisce un'API unificata per caricare immagini bitmap dalla rete, risorse, file system e Content Provider, con memorizzazione nella cache automatica a più livelli.

A differenza di Glide e Picasso, Coil utilizza Kotlin Coroutines invece di catene di callback, rendendo il codice più lineare e prevedibile. Tutte le operazioni di caricamento e decodifica vengono eseguite su thread in background tramite il dispatcher Dispatchers.IO, con risultati consegnati al thread principale senza commutazione esplicita.

Coil supporta trasformazioni (Round, Blur, Grayscale), animazioni di transizione, SVG e GIF, nonché Target personalizzati per visualizzazioni non standard. Secondo Google I/O 2023, Coil è raccomandato nei tutorial ufficiali di Jetpack Compose insieme a Glide.

  • Dimensioni APK — circa 150 KB (contro 500 KB di Glide)
  • Versione minima Android — API 21 (Lollipop)
  • Dipendenza — Kotlin Coroutines (integrata)

Come funziona Coil: ImageLoader e ImageRequest

ImageLoader è il componente principale di Coil, responsabile dell'esecuzione delle richieste di caricamento e della gestione della cache. Ogni istanza contiene riferimenti a MemoryCache, DiskCache, BitmapPool e un pool di coroutine. Per impostazione predefinita, viene utilizzato un singleton creato tramite Coil.imageLoader(context).

ImageRequest

ImageRequest è un oggetto che descrive una singola richiesta di caricamento immagine: origine dati (URL, URI, risorsa Int), ImageView o Target di destinazione, trasformazioni, impostazioni della cache e placeholder. ImageRequest viene costruito tramite un builder, garantendo flessibilità e leggibilità.

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()

Una volta costruito, ImageRequest viene passato a ImageLoader tramite enqueue o execute. Il metodo enqueue avvia una coroutine e restituisce un Disposable, consentendo di annullare il caricamento quando si esce dallo schermo. Il metodo execute è una funzione suspend che restituisce direttamente un Result.

Flusso di esecuzione della richiesta

ImageLoader controlla sequenzialmente MemoryCache, DiskCache e solo in caso di mancata corrispondenza di entrambi esegue una richiesta di rete tramite HttpEngine. Dopo il caricamento, i byte vengono decodificati in un Bitmap considerando la dimensione target, vengono applicate le trasformazioni, il risultato viene memorizzato in entrambe le cache e passato al Target.

  • Memory Cache — controllato per primo, chiave è URL + parametri
  • Disk Cache — controllato in caso di mancanza in memoria, chiave è MD5 dell'URL
  • HttpEngine — OkHttp per impostazione predefinita, personalizzabile tramite componente

Componenti principali di Coil

Coil è costruito su un'architettura a componenti con la possibilità di sostituire qualsiasi parte tramite Dependency Injection. Tutti i componenti vengono registrati in ImageLoaderFactory e passati al costruttore di ImageLoader tramite il builder.

ImageLoader

ImageLoader è il punto di ingresso per tutte le operazioni di caricamento. Ogni istanza contiene un pool di coroutine, BitmapPool, MemoryCache, DiskCache e un elenco di intercettatori. Per impostazione predefinita, viene creata un'istanza globale, ma per i test unitari è possibile creare istanze separate con cache isolate.

MemoryCache

MemoryCache è una cache in memoria basata su LRU (Least Recently Used) che memorizza oggetti Bitmap decodificati. La dimensione massima predefinita è il 25% della memoria disponibile dell'applicazione, ma non inferiore a 32 MB. La chiave della cache è formata da URL + dimensione + trasformazioni, impedendo il recupero di immagini obsolete.

DiskCache

DiskCache è una cache basata su file per dati grezzi (JPEG, PNG, WebP) e metadati decodificati. Si trova nella directory della cache dell'applicazione e supporta la pulizia automatica quando il limite viene superato. Le operazioni su disco vengono eseguite tramite DiskCache.Builder con configurazione della directory e della dimensione massima.

Livelli di cache in Coil

Coil implementa una strategia di caching multilivello che minimizza le richieste di rete e accelera la visualizzazione delle immagini. Ogni livello ha il proprio scopo e durata dei dati.

LivelloTipo di archiviazioneDurataDimensione predefinita
Memory CacheBitmap in RAMFino allo sfratto LRU25% dell'heap, da 32 MB
Disk CacheFile JPEG/WebPFino al superamento del limite250 MB
Http CacheRisposte OkHttpSecondo le intestazioni Cache-ControlDipende dal client HTTP

Memory Cache fornisce accesso immediato ai Bitmap già decodificati. Disk Cache garantisce che l'app funzioni senza rete (offline-first) dopo il primo caricamento. Http Cache a livello OkHttp gestisce richieste condizionali con ETag e If-Modified-Since.

Le politiche di cache sono configurate per richiesta tramite CachePolicy con tre valori: ENABLED, READ_ONLY, WRITE_ONLY, DISABLED. Ad esempio, per gli avatar degli utenti, è possibile impostare READ_ONLY per Memory Cache e ENABLED per Disk Cache.

Esempi di utilizzo di Coil in Kotlin

Coil fornisce diversi metodi di integrazione a seconda dell'architettura dell'applicazione. Esaminiamo tre scenari chiave con esempi di codice funzionanti.

Caricamento in ImageView tramite estensione

load è una funzione di estensione per ImageView, il modo più semplice per caricare un'immagine in una riga. La funzione accetta URL, URI, risorsa Int o File, insieme a tutti i parametri opzionali tramite un configuratore lambda.

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

Il metodo load restituisce un Disposable, che può essere annullato in onDestroy o durante il riutilizzo della View. Ciò previene perdite di memoria e richieste di rete non necessarie durante lo scorrimento rapido delle liste.

Utilizzo in Jetpack Compose

AsyncImage è una funzione composable per caricare immagini in UI dichiarativa. Accetta qualsiasi fonte di dati e tre parametri opzionali per gli stati: placeholder, error e success.

kotlin
@Composable
fun NetworkImage(url: String) {
    AsyncImage(
        model = url,
        contentDescription = "immagine di rete",
        placeholder = ColorPainter(Color.Gray),
        error = ColorPainter(Color.Red)
    )
}

SubcomposeAsyncImage è una versione più flessibile che consente di personalizzare la visualizzazione durante il caricamento tramite uno slot di contenuto. Questo è utile per scheletri (shimmer) e barre di progresso.

Target personalizzato per output non standard

Se ImageView o AsyncImage non sono adatti, è possibile implementare un Target con un singolo metodo onSuccess che accetta un Bitmap. Viene utilizzato per il caricamento in Notification, RemoteViews o texture 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()
)

Confronto di Coil con altre librerie

La scelta della libreria di caricamento immagini dipende dai requisiti del progetto. Coil compete con Glide e Picasso, ciascuno con i propri punti di forza. Un confronto delle caratteristiche principali è presentato nella tabella.

CaratteristicaCoilGlidePicasso
LinguaggioKotlin (100%)Java + KotlinJava
Dimensioni APK~150 KB~500 KB~120 KB
CoroutineIntegrateNo (callback)No (callback)
Jetpack ComposeSupporto nativoTramite accompanistDi terze parti
GIF/WebPSì (integrato)Sì (integrato)No
Raccomandazione GoogleSì (I/O 2023)No

Per i nuovi progetti su Kotlin e Jetpack Compose, Coil diventa la scelta naturale grazie a zero dipendenze aggiuntive di coroutine e dimensioni minime. Glide rimane preferito per scenari complessi con animazioni e anteprime video. Picasso è inferiore a entrambi in funzionalità ma vince in semplicità.

Configurazione di Coil in un progetto Android

L'aggiunta di Coil a un progetto Android avviene tramite una dipendenza Gradle. Dopo l'aggiunta, la libreria registra automaticamente un ImageLoader tramite ContentProvider, quindi non è necessaria l'inizializzazione manuale in Application. Se è necessaria la personalizzazione, viene creato un ImageLoader personalizzato tramite il builder.

kotlin
// build.gradle.kts (app module)
dependencies {
    implementation("io.coil-kt:coil:2.6.0")
    // Per Jetpack Compose in aggiunta:
    implementation("io.coil-kt:coil-compose:2.6.0")
    // Per supporto SVG:
    implementation("io.coil-kt:coil-svg:2.6.0")
    // Per supporto GIF:
    implementation("io.coil-kt:coil-gif:2.6.0")
}

Per personalizzare ImageLoader, viene utilizzato ImageLoaderFactory — un singleton creato in Application.onCreate. Nella factory è possibile configurare i limiti della cache, il client HTTP, i decoder personalizzati e la registrazione. Per impostazione predefinita, Coil utilizza OkHttp con un pool di connessioni pronto.

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()
    }
}

Domande frequenti

Cos'è Coil e a cosa serve?

Coil è una libreria per il caricamento di immagini su Android, scritta in Kotlin utilizzando coroutine. Viene utilizzata per il caricamento asincrono, la memorizzazione nella cache e la visualizzazione di immagini bitmap dalla rete, risorse o file system.

In cosa differisce Coil da Glide?

Coil è scritto al 100% in Kotlin e utilizza coroutine invece del meccanismo di callback di Glide. Coil ha dimensioni APK inferiori (~150 KB contro ~500 KB) e supporto nativo per Jetpack Compose tramite AsyncImage.

Come aggiungere Coil a un progetto Kotlin?

Aggiungi la dipendenza io.coil-kt:coil:2.6.0 in build.gradle.kts. Per Jetpack Compose, aggiungi anche io.coil-kt:coil-compose:2.6.0. La libreria registra automaticamente un ImageLoader tramite ContentProvider.

Quali tipi di immagini supporta Coil?

Coil supporta JPEG, PNG, WebP, BMP, SVG (tramite il modulo coil-svg) e GIF (tramite il modulo coil-gif). I formati AVIF e HEIF sono supportati tramite un decoder personalizzato su dispositivi con Android 10+.

Come configurare la cache in Coil?

La cache viene configurata tramite ImageLoader.Builder: memoryCache specificando la percentuale di heap, diskCache con percorso e limite in byte. Le politiche di cache (ENABLED, DISABLED, READ_ONLY) vengono configurate per richiesta tramite CachePolicy.

Riepilogo

  • Coil è una libreria di caricamento immagini per Kotlin con supporto completo di coroutine e Jetpack Compose.
  • ImageLoader gestisce richieste, caching e trasformazioni, utilizzando due livelli di cache: Memory Cache e Disk Cache.
  • AsyncImage e SubcomposeAsyncImage forniscono integrazione con Compose, supportando stati placeholder, error e success.
  • Dimensioni APK ~150 KB rendono Coil una delle librerie di caricamento immagini più compatte sul mercato.
  • Trasformazioni (RoundedCorners, CircleCrop, Blur) sono integrate nella libreria e funzionano con accelerazione hardware.
  • Disk Cache fornisce accesso offline alle immagini caricate in precedenza con un limite di archiviazione configurabile.
  • Coil è raccomandato da Google nelle guide ufficiali di Jetpack Compose, confermando il suo status di standard moderno.

Svilupperemo un'applicazione mobile chiavi in mano

IT Sectr crea applicazioni iOS e Android per startup e aziende dal 2017. Ti consulteremo e ti proporremo la soluzione migliore.

Discuti il progetto

Leggi anche