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 се изгражда чрез builder, което осигурява гъвкавост и четимост.

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.

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

Основни компоненти на Coil

Coil е изграден върху компонентна архитектура с възможност за замяна на всяка част чрез Dependency Injection. Всички компоненти се регистрират в ImageLoaderFactory и се предават в конструктора на ImageLoader чрез builder.

ImageLoader

ImageLoader — входна точка за всички операции по зареждане. Всеки екземпляр съдържа пул от корутини, BitmapPool, MemoryCache, DiskCache и списък от интерсептори. По подразбиране се създава един глобален екземпляр, но за модулно тестване могат да се създават отделни екземпляри с изолиран кеш.

MemoryCache

MemoryCache — кеш в паметта, базиран на 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 CacheJPEG/WebP файловеДо превишаване на лимита250 MB
Http CacheOkHttp отговориСпоред Cache-Control заглавкиЗависи от HTTP клиента

Memory Cache осигурява моментален достъп до вече декодирани битмапове. 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 — функция-разширение за 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Естествена поддръжкаЧрез AccompanimentТрета страна
GIF/WebPДа (вградено)Да (вградено)Не
Препоръка от GoogleДа (I/O 2023)ДаНе

За нови проекти на Kotlin и Jetpack Compose Coil се превръща в естествен избор благодарение на нулевата допълнителна зависимост от корутини и минималния размер. Glide остава предпочитан за сложни сценарии с анимации и видео прегледи. Picasso отстъпва и на двете по функционалност, но печели по простота.

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

Свързването на Coil с Android проект се извършва чрез Gradle зависимост. След добавяне библиотеката автоматично регистрира ImageLoader чрез ContentProvider, така че ръчна инициализация в Application не е необходима. При нужда от персонализиране се създава собствен ImageLoader чрез builder.

kotlin
// build.gradle.kts (модул на приложението)
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 г. Ще ви консултираме и ще предложим най-доброто решение.

Обсъдете проекта

Прочетете също