Coil — је библиотека за учитавање слика на Android-у, написана у Kotlin-у и изграђена на бази корутина. Према званичној документацији, библиотека подржава Memory Cache, Disk Cache и трансформације са хардверским убрзањем. Coil се истиче минималном величином APK-а (око 150 KB) и потпуном компатибилношћу са Jetpack Compose-ом.
Главне тачке
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-ом.
ImageLoader — главна компонента Coil-а задужена за извршавање захтева за учитавање и управљање кешом. Свака инстанца садржи референце на MemoryCache, DiskCache, BitmapPool и пул корутина. Подразумевано се користи синглтон креиран кроз Coil.imageLoader(context).
ImageRequest — објекат који описује један захтев за учитавање слике: извор података (URL, URI, Int ресурс), циљни ImageView или Target, трансформације, поставке кеширања и placeholder. ImageRequest се саставља кроз builder, што обезбеђује флексибилност и читљивост.
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-у.
Coil је изграђен на компонентној архитектури са могућношћу замене било ког дела кроз Dependency Injection. Све компоненте се региструју у ImageLoaderFactory и прослеђују у конструктор ImageLoader-а кроз builder.
ImageLoader — улазна тачка за све операције учитавања. Свака инстанца садржи пул корутина, BitmapPool, MemoryCache, DiskCache и листу пресретача. Подразумевано се креира једна глобална инстанца, али за модуларно тестирање се могу креирати одвојене инстанце са изолованим кешом.
MemoryCache — кеш у меморији заснован на LRU (Least Recently Used) који чува декодиране Bitmap објекте. Подразумевана максимална величина је 25% доступне меморије апликације, али не мање од 32 MB. Кључ кеша се формира од URL-а + величине + трансформација, што искључује издавање неажурне слике.
DiskCache — фајл кеш за сирове податке (JPEG, PNG, WebP) и декодиране метаподатке. Налази се у кеш директоријуму апликације и подржава аутоматско чишћење при прекорачењу лимита. Рад са диском се извршава кроз DiskCache.Builder са подешавањем директоријума и максималне величине.
Coil имплементира вишеслојну стратегију кеширања која минимизира мрежне захтеве и убрзава приказ слика. Сваки ниво има своју сврху и време живота података.
| Ниво | Тип складиштења | Време живота | Подразумевана величина |
|---|---|---|---|
| Memory Cache | Bitmap у меморији | До истискивања LRU | 25% heap, од 32 MB |
| Disk Cache | JPEG/WebP датотеке | До прекорачења лимита | 250 MB |
| Http Cache | OkHttp одговори | Према 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 нуди неколико начина интеграције у зависности од архитектуре апликације. Размотримо три кључна сценарија са радним примерима кода.
load — екстензија функција за ImageView, најједноставнији начин да се учита слика у једном реду. Функција прихвата URL, URI, Int ресурс или File и све опционе параметре кроз ламбда конфигуратор.
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-а. Ово спречава цурење меморије и непотребне мрежне захтеве при брзом скроловању листе.
AsyncImage — composable функција за учитавање слика у декларативном UI-ју. Прихвата било који извор података и три опциона параметра за стања: placeholder, error и success.
@Composable
fun NetworkImage(url: String) {
AsyncImage(
model = url,
contentDescription = "мрежна слика",
placeholder = ColorPainter(Color.Gray),
error = ColorPainter(Color.Red)
)
}
SubcomposeAsyncImage — флексибилнија верзија која омогућава прилагођавање приказа током учитавања кроз content слот. Ово је корисно за скелетоне (shimmer) и траке напретка.
Ако ImageView или AsyncImage нису одговарајући, може се имплементирати Target са јединственим методом onSuccess који прима Bitmap. Ово се користи за учитавање у Notification, RemoteViews или OpenGL текстуру.
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-ом, од којих свака има своје предности. Поређење главних карактеристика је приказано у табели.
| Карактеристика | Coil | Glide | Picasso |
|---|---|---|---|
| Језик | Kotlin (100%) | Java + Kotlin | Java |
| Величина 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 пројектом се врши кроз Gradle зависност. Након додавања, библиотека аутоматски региструје ImageLoader кроз ContentProvider, тако да ручна иницијализација у Application-у није потребна. По потреби прилагођавања, креира се сопствени ImageLoader кроз builder.
// 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 са готовим пулом веза.
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 — библиотека за учитавање слика на Android-у, написана у Kotlin-у коришћењем корутина. Користи се за асинхроно учитавање, кеширање и приказ битмап слика из мреже, ресурса или фајл система.
Coil је написан 100% у Kotlin-у и користи корутине уместо callback механизма у Glide-у. Coil има мању величину APK-а (~150 KB наспрам ~500 KB) и изворну подршку за Jetpack Compose кроз AsyncImage.
Додајте зависност io.coil-kt:coil:2.6.0 у build.gradle.kts. За Jetpack Compose такође додајте io.coil-kt:coil-compose:2.6.0. Библиотека аутоматски региструје ImageLoader кроз ContentProvider.
Coil подржава JPEG, PNG, WebP, BMP, SVG (кроз модул coil-svg) и GIF (кроз модул coil-gif). AVIF и HEIF формати се подржавају кроз прилагођени декодер на уређајима са Android 10+.
Кеш се подешава кроз ImageLoader.Builder: memoryCache са навођењем процента од heap-а, diskCache са путањом и лимитом у бајтовима. Политике кеша (ENABLED, DISABLED, READ_ONLY) се подешавају по захтеву кроз CachePolicy.
Резиме
Развићемо мобилну апликацију под кључ
IT Sectr креира iOS и Android апликације за стартапе и предузећа од 2017. године. Саветоваћемо вас и предложити најбоље решење.
Прочитајте такође