Coil — qué es, conceptos clave e ImageLoader en Android

Autor: IT Sectr Publicado: 2026-05-05 Tiempo de lectura: 9 min

Coil es una librería para cargar imágenes en Android, escrita en Kotlin y construida sobre corrutinas. Según la documentación oficial, la librería admite Memory Cache, Disk Cache y transformaciones con aceleración por hardware. Coil destaca por su tamaño mínimo de APK (aproximadamente 150 KB) y su total compatibilidad con Jetpack Compose.

Puntos clave

  • Coil es una librería para cargar imágenes en Android que utiliza Kotlin Coroutines y Kotlin Serialization.
  • ImageLoader es el componente central que gestiona las solicitudes, el almacenamiento en caché y las transformaciones de imágenes.
  • Memory Cache almacena imágenes de mapa de bits decodificadas en RAM para acceso instantáneo.
  • Disk Cache guarda archivos comprimidos en el almacenamiento para trabajo sin conexión y reducción de tráfico.
  • Jetpack Compose — la librería es compatible con AsyncImage y SubcomposeAsyncImage para UI declarativa.

¿Qué es Coil?

Coil (Coroutine Image Loader) es una librería para cargar imágenes en Android, escrita completamente en Kotlin y que utiliza corrutinas para operaciones asíncronas. Proporciona una API unificada para cargar imágenes de mapa de bits desde la red, recursos, sistema de archivos y Content Provider, con almacenamiento en caché automático de múltiples niveles.

A diferencia de Glide y Picasso, Coil utiliza Kotlin Coroutines en lugar de cadenas de callbacks, lo que hace que el código sea más lineal y predecible. Todas las operaciones de carga y decodificación se ejecutan en hilos de fondo a través del dispatcher Dispatchers.IO, y los resultados se entregan al hilo principal sin cambios explícitos.

Coil admite transformaciones (Round, Blur, Grayscale), animaciones de transición, SVG y GIF, así como Targets personalizados para visualización no estándar. Según Google I/O 2023, Coil está recomendado en tutoriales oficiales de Jetpack Compose junto con Glide.

  • Tamaño del APK — aproximadamente 150 KB (frente a 500 KB de Glide)
  • Versión mínima de Android — API 21 (Lollipop)
  • Dependencia — Kotlin Coroutines (integrada)

Cómo funciona Coil: ImageLoader e ImageRequest

ImageLoader es el componente principal de Coil, responsable de ejecutar las solicitudes de carga y gestionar la caché. Cada instancia contiene referencias a MemoryCache, DiskCache, BitmapPool y un grupo de corrutinas. Por defecto, se utiliza un singleton creado mediante Coil.imageLoader(context).

ImageRequest

ImageRequest es un objeto que describe una única solicitud de carga de imagen: origen de datos (URL, URI, recurso Int), ImageView o Target de destino, transformaciones, configuración de caché y placeholder. ImageRequest se construye mediante un builder, lo que garantiza flexibilidad y legibilidad.

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 vez construido, ImageRequest se pasa a ImageLoader mediante enqueue o execute. El método enqueue inicia una corrutina y devuelve un Disposable, que permite cancelar la carga al salir de la pantalla. El método execute es una función suspend que devuelve un Result directamente.

Flujo de ejecución de la solicitud

ImageLoader verifica secuencialmente MemoryCache, DiskCache y solo si ambos fallan, ejecuta una solicitud de red a través de HttpEngine. Después de la carga, los bytes se decodifican en un Bitmap considerando el tamaño de destino, se aplican las transformaciones, el resultado se almacena en ambas cachés y se pasa al Target.

  • Memory Cache — se verifica primero, clave es URL + parámetros
  • Disk Cache — se verifica si falla la memoria, clave es MD5 de la URL
  • HttpEngine — OkHttp por defecto, personalizable mediante componente

Componentes principales de Coil

Coil está construido sobre una arquitectura de componentes con capacidad de reemplazar cualquier parte mediante Inyección de Dependencias. Todos los componentes se registran en ImageLoaderFactory y se pasan al constructor de ImageLoader a través del builder.

ImageLoader

ImageLoader es el punto de entrada para todas las operaciones de carga. Cada instancia contiene un grupo de corrutinas, BitmapPool, MemoryCache, DiskCache y una lista de interceptores. Por defecto, se crea una instancia global, pero para pruebas unitarias se pueden crear instancias separadas con cachés aislados.

MemoryCache

MemoryCache es una caché en memoria basada en LRU (Least Recently Used) que almacena objetos Bitmap decodificados. El tamaño máximo por defecto es el 25% de la memoria disponible de la aplicación, pero no menos de 32 MB. La clave de caché se forma a partir de URL + tamaño + transformaciones, lo que evita la recuperación de imágenes desactualizadas.

DiskCache

DiskCache es una caché basada en archivos para datos sin procesar (JPEG, PNG, WebP) y metadatos decodificados. Se ubica en el directorio de caché de la aplicación y admite limpieza automática al superar el límite. Las operaciones de disco se realizan mediante DiskCache.Builder con configuración de directorio y tamaño máximo.

Niveles de caché en Coil

Coil implementa una estrategia de almacenamiento en caché multinivel que minimiza las solicitudes de red y acelera la visualización de imágenes. Cada nivel tiene su propio propósito y tiempo de vida de los datos.

NivelTipo de almacenamientoTiempo de vidaTamaño por defecto
Memory CacheBitmap en RAMHasta desalojo LRU25% del heap, desde 32 MB
Disk CacheArchivos JPEG/WebPHasta superar el límite250 MB
Http CacheRespuestas OkHttpSegún cabeceras Cache-ControlDepende del cliente HTTP

Memory Cache proporciona acceso instantáneo a los Bitmaps ya decodificados. Disk Cache garantiza que la aplicación funcione sin red (offline-first) después de la primera carga. Http Cache a nivel de OkHttp maneja solicitudes condicionales con ETag e If-Modified-Since.

Las políticas de caché se configuran por solicitud mediante CachePolicy con tres valores: ENABLED, READ_ONLY, WRITE_ONLY, DISABLED. Por ejemplo, para avatares de usuarios, se puede establecer READ_ONLY para Memory Cache y ENABLED para Disk Cache.

Ejemplos de uso de Coil en Kotlin

Coil proporciona varios métodos de integración según la arquitectura de la aplicación. Veamos tres escenarios clave con ejemplos de código funcionales.

Carga en ImageView mediante extensión

load es una función de extensión para ImageView, la forma más sencilla de cargar una imagen en una línea. La función acepta una URL, URI, recurso Int o File, junto con todos los parámetros opcionales mediante un configurador lambda.

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

El método load devuelve un Disposable, que se puede cancelar en onDestroy o al reutilizar la View. Esto evita fugas de memoria y solicitudes de red innecesarias durante el desplazamiento rápido de listas.

Uso en Jetpack Compose

AsyncImage es una función composable para cargar imágenes en UI declarativa. Acepta cualquier fuente de datos y tres parámetros opcionales para estados: placeholder, error y success.

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

SubcomposeAsyncImage es una versión más flexible que permite personalizar la visualización durante la carga mediante un slot de contenido. Esto es útil para esqueletos (shimmer) y barras de progreso.

Target personalizado para salida no estándar

Si ImageView o AsyncImage no son adecuados, se puede implementar un Target con un único método onSuccess que acepta un Bitmap. Esto se utiliza para cargar en Notification, RemoteViews o texturas 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()
)

Comparación de Coil con otras librerías

La elección de la librería de carga de imágenes depende de los requisitos del proyecto. Coil compite con Glide y Picasso, cada una con sus puntos fuertes. En la tabla se presenta una comparación de las características principales.

CaracterísticaCoilGlidePicasso
IdiomaKotlin (100%)Java + KotlinJava
Tamaño del APK~150 KB~500 KB~120 KB
CorrutinasIntegradasNo (callbacks)No (callbacks)
Jetpack ComposeSoporte nativoMediante accompanistDe terceros
GIF/WebPSí (integrado)Sí (integrado)No
Recomendación de GoogleSí (I/O 2023)No

Para proyectos nuevos en Kotlin y Jetpack Compose, Coil se convierte en la elección natural gracias a cero dependencias adicionales de corrutinas y tamaño mínimo. Glide sigue siendo preferible para escenarios complejos con animaciones y vistas previas de video. Picasso es inferior a ambas en funcionalidad, pero gana en simplicidad.

Configuración de Coil en un proyecto Android

La incorporación de Coil a un proyecto Android se realiza mediante una dependencia de Gradle. Después de agregarla, la librería registra automáticamente un ImageLoader a través de ContentProvider, por lo que no se requiere inicialización manual en Application. Si se necesita personalización, se crea un ImageLoader personalizado mediante el builder.

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

Para personalizar ImageLoader, se utiliza ImageLoaderFactory — un singleton creado en Application.onCreate. En la fábrica se pueden configurar los límites de caché, el cliente HTTP, los decodificadores personalizados y el registro. Por defecto, Coil utiliza OkHttp con un grupo de conexiones preparado.

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

Preguntas frecuentes

¿Qué es Coil y para qué se utiliza?

Coil es una librería para cargar imágenes en Android, escrita en Kotlin y que utiliza corrutinas. Se utiliza para la carga asíncrona, almacenamiento en caché y visualización de imágenes de mapa de bits desde la red, recursos o sistema de archivos.

¿En qué se diferencia Coil de Glide?

Coil está escrito 100% en Kotlin y utiliza corrutinas en lugar del mecanismo de callbacks de Glide. Coil tiene un tamaño de APK menor (~150 KB frente a ~500 KB) y soporte nativo para Jetpack Compose mediante AsyncImage.

¿Cómo agregar Coil a un proyecto Kotlin?

Agregue la dependencia io.coil-kt:coil:2.6.0 a build.gradle.kts. Para Jetpack Compose, agregue también io.coil-kt:coil-compose:2.6.0. La librería registra automáticamente un ImageLoader mediante ContentProvider.

¿Qué tipos de imágenes admite Coil?

Coil admite JPEG, PNG, WebP, BMP, SVG (mediante el módulo coil-svg) y GIF (mediante el módulo coil-gif). Los formatos AVIF y HEIF se admiten mediante un decodificador personalizado en dispositivos con Android 10+.

¿Cómo configurar la caché en Coil?

La caché se configura mediante ImageLoader.Builder: memoryCache especificando el porcentaje del heap, diskCache con la ruta y el límite en bytes. Las políticas de caché (ENABLED, DISABLED, READ_ONLY) se configuran por solicitud mediante CachePolicy.

Resumen

  • Coil es una librería de carga de imágenes para Kotlin con soporte completo de corrutinas y Jetpack Compose.
  • ImageLoader gestiona solicitudes, almacenamiento en caché y transformaciones, utilizando dos niveles de caché: Memory Cache y Disk Cache.
  • AsyncImage y SubcomposeAsyncImage proporcionan integración con Compose, admitiendo estados de placeholder, error y éxito.
  • Tamaño del APK ~150 KB convierte a Coil en una de las librerías de carga de imágenes más compactas del mercado.
  • Transformaciones (RoundedCorners, CircleCrop, Blur) están integradas en la librería y funcionan con aceleración por hardware.
  • Disk Cache proporciona acceso sin conexión a imágenes cargadas previamente con un límite de almacenamiento configurable.
  • Coil está recomendado por Google en guías oficiales de Jetpack Compose, lo que confirma su estatus como estándar moderno.

Desarrollaremos una aplicación móvil llave en mano

IT Sectr crea aplicaciones para iOS y Android para startups y empresas desde 2017. Le asesoraremos y le propondremos la mejor solución.

Discutir el proyecto

Lea también