Coil — что это, ключевые понятия и ImageLoader в Android

Автор: IT Sectr Опубликовано: 2026-05-05 Время чтения: 9 мин

Coil — это библиотека для загрузки изображений на Android, написанная на Kotlin и построенная на базе корутин. По данным официальной документации, библиотека поддерживает Memory Cache, Disk Cache и трансформации с аппаратным ускорением. Coil выделяется минимальным размером APK (около 150 KB) и полной совместимостью с Jetpack Compose.

Главное

  • Coil — библиотека для загрузки изображений на Android, использующая Kotlin Coroutines и Kotlin Serialization.
  • ImageLoader — центральный компонент, управляющий запросами, кэшированием и трансформациями изображений.
  • Memory Cache хранит декодированные растровые изображения в оперативной памяти для мгновенного доступа.
  • Disk Cache сохраняет сжатые файлы на накопителе для автономной работы и снижения трафика.
  • Jetpack Compose — библиотека поддерживает AsyncImage и SubcomposeAsyncImage для декларативного UI.

Что такое Coil?

Coil (Coroutine Image Loader) — это библиотека для загрузки изображений на Android, полностью написанная на Kotlin и использующая корутины для асинхронной работы. Она предоставляет единый API для загрузки растровых изображений из сети, ресурсов, файловой системы и Content Provider, с автоматическим кэшированием на нескольких уровнях.

В отличие от Glide и Picasso, Coil использует Kotlin Coroutines вместо callback-цепочки, что делает код более линейным и предсказуемым. Все операции загрузки и декодирования выполняются на фоновых потоках через диспетчер Dispatchers.IO, а результат доставляется в главный поток без явного переключения.

Coil поддерживает трансформации (Round, Blur, Grayscale), анимацию переходов, SVG и GIF, а также кастомные Target для нестандартного отображения. По данным Google I/O 2023, Coil рекомендован в официальных туториалах по Jetpack Compose наравне с Glide.

  • Размер APK — около 150 KB (против 500 KB у Glide)
  • Минимальная версия Android — API 21 (Lollipop)
  • Зависимость — Kotlin Coroutines (встроена)

Как работает Coil: ImageLoader и ImageRequest

ImageLoader — основной компонент Coil, отвечающий за выполнение запросов загрузки и управление кэшем. Каждый экземпляр содержит ссылки на MemoryCache, DiskCache, BitmapPool и пул корутин. По умолчанию используется синглтон, создаваемый через Coil.imageLoader(context).

ImageRequest

ImageRequest — объект, описывающий один запрос на загрузку изображения: источник данных (URL, URI, Int ресурс), целевой ImageView или Target, трансформации, настройки кэширования и placeholder. 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 передаётся в ImageLoader через enqueue или execute. Метод enqueue запускает корутину и возвращает Disposable, позволяющий отменить загрузку при уходе с экрана. Метод execute — suspend-функция, возвращающая Result напрямую.

Поток выполнения запроса

ImageLoader последовательно проверяет MemoryCache, DiskCache и только при промахе обоих выполняет сетевой запрос через HttpEngine. После загрузки байты декодируются в Bitmap с учётом target size, применяются трансформации, результат сохраняется в оба кэша и передаётся в Target.

  • Memory Cache — проверка в первую очередь, ключ — URL + параметры
  • Disk Cache — проверка при отсутствии в памяти, ключ — MD5 URL
  • HttpEngine — по умолчанию OkHttp, кастомизируемый через компонент

Основные компоненты Coil

Coil построен на компонентной архитектуре с возможностью замены любой части через Dependency Injection. Все компоненты регистрируются в ImageLoaderFactory и передаются в конструктор ImageLoader через билдер.

ImageLoader

ImageLoader — точка входа для всех операций загрузки. Каждый инстанс содержит пул корутин, BitmapPool, MemoryCache, DiskCache и список перехватчиков. По умолчанию создаётся один глобальный инстанс, но для модульного тестирования можно создавать отдельные экземпляры с изолированным кэшем.

MemoryCache

MemoryCache — in-memory кэш на основе LRU (Least Recently Used), хранящий декодированные Bitmap-объекты. Максимальный размер по умолчанию — 25% доступной памяти приложения, но не менее 32 MB. Ключ кэша формируется из URL + размера + трансформаций, что исключает выдачу неактуального изображения.

DiskCache

DiskCache — файловый кэш для сырых данных (JPEG, PNG, WebP) и декодированных метаданных. Размещается в кэш-директории приложения и поддерживает автоматическую очистку при превышении лимита. Работа с диском выполняется через DiskCache.Builder с настройкой директории и максимального размера.

Уровни кэширования в Coil

Coil реализует многоуровневую стратегию кэширования, минимизирующую сетевые запросы и ускоряющую отображение изображений. Каждый уровень имеет свою цель и время жизни данных.

УровеньТип храненияВремя жизниРазмер по умолчанию
Memory CacheBitmap в памятиДо вытеснения LRU25% heap, от 32 MB
Disk CacheФайлы JPEG/WebPДо превышения лимита250 MB
Http CacheОтветы OkHttpПо заголовкам Cache-ControlЗависит от HTTP-клиента

Memory Cache обеспечивает мгновенный доступ к уже декодированным Bitmap. Disk Cache гарантирует работу приложения без сети (offline-first) после первой загрузки. Http Cache на уровне OkHttp обрабатывает условные запросы ETag и If-Modified-Since.

Политики кэширования настраиваются пер-запрос через CachePolicy с тремя значениями: ENABLED, READ_ONLY, WRITE_ONLY, DISABLED. Например, для аватаров пользователей можно установить READ_ONLY для Memory Cache и ENABLED для Disk Cache.

Примеры использования Coil на Kotlin

Coil предоставляет несколько способов интеграции в зависимости от архитектуры приложения. Рассмотрим три ключевых сценария с рабочими примерами кода.

Загрузка в ImageView через расширение

load — extension-функция для ImageView, самый простой способ загрузить изображение одной строкой. Функция принимает 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 — composable-функция для загрузки изображений в декларативном UI. Принимает любой источник данных и три опциональных параметра для состояний: placeholder, error и success.

kotlin
@Composable
fun NetworkImage(url: String) {
    AsyncImage(
        model = url,
        contentDescription = "сетевое изображение",
        placeholder = ColorPainter(Color.Gray),
        error = ColorPainter(Color.Red)
    )
}

SubcomposeAsyncImage — более гибкая версия, позволяющая кастомизировать отображение во время загрузки через content-слот. Это полезно для скелетонов (shimmer) и прогресс-баров.

Кастомный Target для нестандартного вывода

Если ImageView или AsyncImage не подходят, можно реализовать Target с единственным методом onSuccess, принимающим Bitmap. Это используется для загрузки в 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 с другими библиотеками

Выбор библиотеки для загрузки изображений зависит от требований проекта. Coil конкурирует с Glide и Picasso, каждая из которых имеет сильные стороны. Сравнение основных характеристик представлено в таблице.

ХарактеристикаCoilGlidePicasso
ЯзыкKotlin (100%)Java + KotlinJava
Размер APK~150 KB~500 KB~120 KB
КорутиныВстроеныНет (callback)Нет (callback)
Jetpack ComposeНативная поддержкаЧерез аккомпаниментСторонняя
GIF/WebPДа (встроено)Да (встроено)Нет
Рекомендация GoogleДа (I/O 2023)ДаНет

Для новых проектов на Kotlin и Jetpack Compose Coil становится естественным выбором благодаря нулевой дополнительной зависимости от корутин и минимальному размеру. Glide остаётся предпочтительным для сложных сценариев с анимациями и видео-превью. Picasso уступает обеим по функциональности, но выигрывает в простоте.

Настройка Coil в проекте Android

Подключение Coil в проект Android выполняется через Gradle-зависимость. После добавления библиотека автоматически регистрирует ImageLoader через ContentProvider, поэтому ручная инициализация в 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 — библиотека для загрузки изображений на Android, написанная на Kotlin с использованием корутин. Она используется для асинхронной загрузки, кэширования и отображения растровых изображений из сети, ресурсов или файловой системы.

Чем Coil отличается от Glide?

Coil написан на 100% Kotlin и использует корутины вместо callback-механизма в Glide. Coil имеет меньший размер APK (~150 KB против ~500 KB) и нативную поддержку Jetpack Compose через AsyncImage.

Как подключить Coil к проекту на Kotlin?

Добавьте зависимость io.coil-kt:coil:2.6.0 в build.gradle.kts. Для Jetpack Compose также добавьте io.coil-kt:coil-compose:2.6.0. Библиотека автоматически регистрирует ImageLoader через ContentProvider.

Какие типы изображений поддерживает Coil?

Coil поддерживает JPEG, PNG, WebP, BMP, SVG (через модуль coil-svg) и GIF (через модуль coil-gif). Форматы AVIF и HEIF поддерживаются через кастомный декодер на устройствах с Android 10+.

Как настроить кэш в Coil?

Кэш настраивается через ImageLoader.Builder: memoryCache с указанием процента от heap, diskCache с путём и лимитом в байтах. Политики кэша (ENABLED, DISABLED, READ_ONLY) настраиваются пер-запрос через CachePolicy.

Итоги

  • Coil — библиотека загрузки изображений на Kotlin с полной поддержкой корутин и Jetpack Compose.
  • ImageLoader управляет запросами, кэшированием и трансформациями, используя два уровня кэша: Memory Cache и Disk Cache.
  • AsyncImage и SubcomposeAsyncImage предоставляют интеграцию с Compose, поддерживая placeholder, error и success-состояния.
  • Размер APK ~150 KB делает Coil одной из самых компактных библиотек загрузки изображений на рынке.
  • Трансформации (RoundedCorners, CircleCrop, Blur) встроены в библиотеку и работают с аппаратным ускорением.
  • Disk Cache обеспечивает офлайн-доступ к ранее загруженным изображениям с настраиваемым лимитом хранения.
  • Coil рекомендован Google в официальных руководствах по Jetpack Compose, что подтверждает его статус современного стандарта.

Мы разработаем мобильное приложение под ключ

IT Sectr создаёт приложения для iOS и Android для стартапов и бизнеса с 2017 года. Мы проконсультируем вас и предложим наилучшее решение.

Обсудить проект

Читайте также