Coil — co to jest, kluczowe pojęcia i ImageLoader w Androidzie

Autor: IT Sectr Opublikowano: 2026-05-05 Czas czytania: 9 min

Coil — to biblioteka do ładowania obrazów na Androida, napisana w Kotlinie i oparta na korutynach. Według oficjalnej dokumentacji, biblioteka obsługuje Memory Cache, Disk Cache i transformacje z przyspieszeniem sprzętowym. Coil wyróżnia się minimalnym rozmiarem APK (około 150 KB) i pełną zgodnością z Jetpack Compose.

Najważniejsze

  • Coil — biblioteka do ładowania obrazów na Androida, wykorzystująca Kotlin Coroutines i Kotlin Serialization.
  • ImageLoader — centralny komponent zarządzający żądaniami, buforowaniem i transformacjami obrazów.
  • Memory Cache przechowuje zdekodowane obrazy bitmapowe w pamięci RAM dla natychmiastowego dostępu.
  • Disk Cache zapisuje skompresowane pliki na dysku do pracy offline i zmniejszenia ruchu sieciowego.
  • Jetpack Compose — biblioteka obsługuje AsyncImage i SubcomposeAsyncImage dla deklaratywnego UI.

Czym jest Coil?

Coil (Coroutine Image Loader) — to biblioteka do ładowania obrazów na Androida, w całości napisana w Kotlinie i wykorzystująca korutyny do asynchronicznej pracy. Oferuje jednolity interfejs API do ładowania obrazów bitmapowych z sieci, zasobów, systemu plików i Content Provider, z automatycznym buforowaniem na wielu poziomach.

W przeciwieństwie do Glide i Picasso, Coil używa Kotlin Coroutines zamiast łańcuchów wywołań zwrotnych, co sprawia, że kod jest bardziej liniowy i przewidywalny. Wszystkie operacje ładowania i dekodowania są wykonywane w wątkach tła przez dyspozytora Dispatchers.IO, a wynik jest dostarczany do głównego wątku bez jawnego przełączania.

Coil obsługuje transformacje (Round, Blur, Grayscale), animacje przejść, SVG i GIF, a także niestandardowe Target dla nietypowego wyświetlania. Według Google I/O 2023, Coil jest zalecany w oficjalnych tutorialach Jetpack Compose na równi z Glide.

  • Rozmiar APK — około 150 KB (wobec 500 KB w Glide)
  • Minimalna wersja Androida — API 21 (Lollipop)
  • Zależność — Kotlin Coroutines (wbudowana)

Jak działa Coil: ImageLoader i ImageRequest

ImageLoader — główny komponent Coil odpowiedzialny za wykonywanie żądań ładowania i zarządzanie pamięcią podręczną. Każda instancja zawiera odniesienia do MemoryCache, DiskCache, BitmapPool i puli korutyn. Domyślnie używany jest singleton tworzony przez Coil.imageLoader(context).

ImageRequest

ImageRequest — obiekt opisujący pojedyncze żądanie ładowania obrazu: źródło danych (URL, URI, zasób Int), docelowy ImageView lub Target, transformacje, ustawienia buforowania i placeholder. ImageRequest jest budowany przez builder, co zapewnia elastyczność i czytelność.

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

Po zbudowaniu ImageRequest jest przekazywany do ImageLoader przez enqueue lub execute. Metoda enqueue uruchamia korutynę i zwraca Disposable, umożliwiający anulowanie ładowania przy opuszczaniu ekranu. Metoda execute to funkcja zawieszająca, zwracająca Result bezpośrednio.

Przebieg wykonania żądania

ImageLoader kolejno sprawdza MemoryCache, DiskCache i dopiero przy braku trafienia w obu wykonuje żądanie sieciowe przez HttpEngine. Po załadowaniu bajty są dekodowane do Bitmap z uwzględnieniem docelowego rozmiaru, stosowane są transformacje, wynik jest zapisywany w obu pamięciach podręcznych i przekazywany do Target.

  • Memory Cache — sprawdzany w pierwszej kolejności, klucz — URL + parametry
  • Disk Cache — sprawdzany przy braku w pamięci, klucz — MD5 URL
  • HttpEngine — domyślnie OkHttp, konfigurowalny przez komponent

Główne komponenty Coil

Coil jest zbudowany na architekturze komponentowej z możliwością wymiany dowolnej części przez Dependency Injection. Wszystkie komponenty są rejestrowane w ImageLoaderFactory i przekazywane do konstruktora ImageLoader przez builder.

ImageLoader

ImageLoader — punkt wejścia dla wszystkich operacji ładowania. Każda instancja zawiera pulę korutyn, BitmapPool, MemoryCache, DiskCache i listę przechwytywaczy. Domyślnie tworzona jest jedna globalna instancja, ale do testów modułowych można tworzyć osobne egzemplarze z izolowaną pamięcią podręczną.

MemoryCache

MemoryCache — pamięć podręczna in-memory oparta na LRU (Least Recently Used), przechowująca zdekodowane obiekty Bitmap. Domyślny maksymalny rozmiar to 25% dostępnej pamięci aplikacji, ale nie mniej niż 32 MB. Klucz pamięci podręcznej jest tworzony z URL + rozmiaru + transformacji, co eliminuje ryzyko zwrócenia nieaktualnego obrazu.

DiskCache

DiskCache — pamięć podręczna plików dla surowych danych (JPEG, PNG, WebP) i zdekodowanych metadanych. Znajduje się w katalogu pamięci podręcznej aplikacji i obsługuje automatyczne czyszczenie po przekroczeniu limitu. Praca z dyskiem jest wykonywana przez DiskCache.Builder z konfiguracją katalogu i maksymalnego rozmiaru.

Poziomy buforowania w Coil

Coil implementuje wielopoziomową strategię buforowania, minimalizującą żądania sieciowe i przyspieszającą wyświetlanie obrazów. Każdy poziom ma swój cel i czas życia danych.

PoziomTyp przechowywaniaCzas życiaDomyślny rozmiar
Memory CacheBitmap w pamięciDo wyparcia LRU25% heap, od 32 MB
Disk CachePliki JPEG/WebPDo przekroczenia limitu250 MB
Http CacheOdpowiedzi OkHttpWedług nagłówków Cache-ControlZależy od klienta HTTP

Memory Cache zapewnia natychmiastowy dostęp do już zdekodowanych bitmap. Disk Cache gwarantuje działanie aplikacji bez sieci (offline-first) po pierwszym załadowaniu. Http Cache na poziomie OkHttp obsługuje warunkowe żądania ETag i If-Modified-Since.

Polityki buforowania są konfigurowane per-żądanie przez CachePolicy z trzema wartościami: ENABLED, READ_ONLY, WRITE_ONLY, DISABLED. Na przykład dla awatarów użytkowników można ustawić READ_ONLY dla Memory Cache i ENABLED dla Disk Cache.

Przykłady użycia Coil w Kotlinie

Coil oferuje kilka sposobów integracji w zależności od architektury aplikacji. Rozważymy trzy kluczowe scenariusze z działającymi przykładami kodu.

Ładowanie do ImageView przez rozszerzenie

load — funkcja rozszerzająca dla ImageView, najprostszy sposób załadowania obrazu w jednej linijce. Funkcja przyjmuje URL, URI, zasób Int lub File oraz wszystkie opcjonalne parametry przez konfigurator lambda.

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

Metoda load zwraca Disposable, który można anulować w onDestroy lub przy ponownym użyciu View. Zapobiega to wyciekom pamięci i zbędnym żądaniom sieciowym podczas szybkiego przewijania listy.

Użycie w Jetpack Compose

AsyncImage — funkcja composable do ładowania obrazów w deklaratywnym UI. Przyjmuje dowolne źródło danych i trzy opcjonalne parametry dla stanów: placeholder, error i success.

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

SubcomposeAsyncImage — bardziej elastyczna wersja, pozwalająca dostosować wyświetlanie podczas ładowania przez slot content. Jest to przydatne dla szkieletów (shimmer) i pasków postępu.

Niestandardowy Target dla nietypowego wyjścia

Jeśli ImageView lub AsyncImage nie są odpowiednie, można zaimplementować Target z pojedynczą metodą onSuccess przyjmującą Bitmap. Jest to używane do ładowania w Notification, RemoteViews lub tekstury 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()
)

Porównanie Coil z innymi bibliotekami

Wybór biblioteki do ładowania obrazów zależy od wymagań projektu. Coil konkuruje z Glide i Picasso, z których każda ma swoje mocne strony. Porównanie głównych cech przedstawiono w tabeli.

CechaCoilGlidePicasso
JęzykKotlin (100%)Java + KotlinJava
Rozmiar APK~150 KB~500 KB~120 KB
KorutynyWbudowaneNie (callback)Nie (callback)
Jetpack ComposeNatywne wsparciePrzez akompaniamentZewnętrzne
GIF/WebPTak (wbudowane)Tak (wbudowane)Nie
Zalecenie GoogleTak (I/O 2023)TakNie

Dla nowych projektów w Kotlinie i Jetpack Compose Coil staje się naturalnym wyborem dzięki zerowej dodatkowej zależności od korutyn i minimalnemu rozmiarowi. Glide pozostaje preferowany dla złożonych scenariuszy z animacjami i podglądami wideo. Picasso ustępuje obu pod względem funkcjonalności, ale wygrywa prostotą.

Konfiguracja Coil w projekcie Android

Podłączenie Coil do projektu Android odbywa się przez zależność Gradle. Po dodaniu biblioteka automatycznie rejestruje ImageLoader przez ContentProvider, więc ręczna inicjalizacja w Application nie jest wymagana. W razie potrzeby dostosowania tworzy się własny ImageLoader przez builder.

kotlin
// build.gradle.kts (moduł aplikacji)
dependencies {
    implementation("io.coil-kt:coil:2.6.0")
    // Dodatkowo dla Jetpack Compose:
    implementation("io.coil-kt:coil-compose:2.6.0")
    // Dla obsługi SVG:
    implementation("io.coil-kt:coil-svg:2.6.0")
    // Dla obsługi GIF:
    implementation("io.coil-kt:coil-gif:2.6.0")
}

Do dostosowania ImageLoader używa się ImageLoaderFactory — singletonu tworzonego w Application.onCreate. W fabryce można skonfigurować limity pamięci podręcznej, klient HTTP, niestandardowe dekodery i logowanie. Domyślnie Coil używa OkHttp z gotową pulą połączeń.

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

Często zadawane pytania

Czym jest Coil i do czego się go używa?

Coil — biblioteka do ładowania obrazów na Androida, napisana w Kotlinie z wykorzystaniem korutyn. Służy do asynchronicznego ładowania, buforowania i wyświetlania obrazów bitmapowych z sieci, zasobów lub systemu plików.

Czym Coil różni się od Glide?

Coil jest napisany w 100% w Kotlinie i używa korutyn zamiast mechanizmu wywołań zwrotnych w Glide. Coil ma mniejszy rozmiar APK (~150 KB wobec ~500 KB) i natywne wsparcie dla Jetpack Compose przez AsyncImage.

Jak dodać Coil do projektu w Kotlinie?

Dodaj zależność io.coil-kt:coil:2.6.0 w build.gradle.kts. Dla Jetpack Compose dodaj również io.coil-kt:coil-compose:2.6.0. Biblioteka automatycznie rejestruje ImageLoader przez ContentProvider.

Jakie typy obrazów obsługuje Coil?

Coil obsługuje JPEG, PNG, WebP, BMP, SVG (przez moduł coil-svg) i GIF (przez moduł coil-gif). Formaty AVIF i HEIF są obsługiwane przez niestandardowy dekoder na urządzeniach z Androidem 10+.

Jak skonfigurować pamięć podręczną w Coil?

Pamięć podręczną konfiguruje się przez ImageLoader.Builder: memoryCache z określeniem procentu dostępnej pamięci, diskCache ze ścieżką i limitem w bajtach. Polityki pamięci podręcznej (ENABLED, DISABLED, READ_ONLY) są konfigurowane per-żądanie przez CachePolicy.

Podsumowanie

  • Coil — biblioteka do ładowania obrazów w Kotlinie z pełnym wsparciem korutyn i Jetpack Compose.
  • ImageLoader zarządza żądaniami, buforowaniem i transformacjami, korzystając z dwóch poziomów pamięci podręcznej: Memory Cache i Disk Cache.
  • AsyncImage i SubcomposeAsyncImage zapewniają integrację z Compose, obsługując stany placeholder, error i success.
  • Rozmiar APK ~150 KB czyni Coil jedną z najbardziej kompaktowych bibliotek do ładowania obrazów na rynku.
  • Transformacje (RoundedCorners, CircleCrop, Blur) są wbudowane w bibliotekę i działają z przyspieszeniem sprzętowym.
  • Disk Cache zapewnia dostęp offline do wcześniej załadowanych obrazów z konfigurowalnym limitem przechowywania.
  • Coil jest zalecany przez Google w oficjalnych przewodnikach po Jetpack Compose, co potwierdza jego status nowoczesnego standardu.

Opracujemy aplikację mobilną pod klucz

IT Sectr tworzy aplikacje na iOS i Androida dla startupów i firm od 2017 roku. Doradzimy Ci i zaproponujemy najlepsze rozwiązanie.

Omów projekt

Przeczytaj również