Skip to content

Getting Started


Coil has 4 artifacts published to mavenCentral():

  • io.coil-kt:coil: The default artifact, which includes the Coil singleton.
  • io.coil-kt:coil-base: The base artifact, which does not include the Coil singleton. Prefer this artifact if you want to use dependency injection to inject your ImageLoader instance(s).
  • io.coil-kt:coil-gif: Includes a set of decoders to support decoding GIFs. See GIFs for more details.
  • io.coil-kt:coil-svg: Includes a decoder to support decoding SVGs. See SVGs for more details.

If you need transformations that aren't part of the base Coil artifacts, check out the 3rd-party coil-transformations artifact hosted here.

Java 8

Coil requires Java 8 bytecode. To enable Java 8 desugaring by D8:

Gradle (.gradle):

android {
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8

tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile).all {
    kotlinOptions {
        jvmTarget = "1.8"

Gradle Kotlin DSL (.gradle.kts):

android {
    compileOptions {
        sourceCompatibility = JavaVersion.VERSION_1_8
        targetCompatibility = JavaVersion.VERSION_1_8

tasks.withType<KotlinCompile> {
    kotlinOptions {
        jvmTarget = "1.8"


The heart of Coil's API is the ImageLoader. ImageLoaders are service classes that execute Request objects that are passed to them. ImageLoaders expose two methods for image loading:

  • load: Starts an asynchronous request to load the data into the Target.
fun load(request: LoadRequest): RequestDisposable
  • get: A suspend function, which returns a Drawable.
suspend fun get(request: GetRequest): Drawable


If you're using the io.coil-kt:coil artifact, you can set a default ImageLoader instance like so:

Coil.setDefaultImageLoader {
    ImageLoader(context) {
        okHttpClient {

The default ImageLoader is used for any ImageView.load calls. The best place to call setDefaultImageLoader is in your Application class.

Setting a default ImageLoader is optional. If you don't set one, Coil will lazily create a default ImageLoader when needed.

If you're using the io.coil-kt:coil-base artifact, you should create your own ImageLoader instance(s) and inject them throughout your app with dependency injection. Read more about dependency injection here.


If you set a custom OkHttpClient, you must set a cache implementation or the ImageLoader will have no disk cache. A default Coil cache instance can be created using CoilUtils.createDefaultCache.

Extension Functions

Coil provides a set of extension functions for ImageLoaders, ImageViews, and the Coil singleton to provide type-safe methods. Here's an example for loading a URL into an ImageView:


By default, requests are initialized with the options from DefaultRequestOptions, however each individual request can be configured with an optional trailing lambda param:

imageView.load("") {

See the docs here and here for more information.

Supported Data Types

The base data types that are supported by all ImageLoader instances are:

  • String (mapped to a Uri)
  • HttpUrl
  • Uri (android.resource, content, file, http, and https schemes only)
  • File
  • @DrawableRes Int
  • Drawable
  • Bitmap


To preload an image into memory, execute a load request without a Target:

Coil.load(context, "")

To only preload the image into the disk cache, disable the memory cache for the request:

Coil.load(context, "") {

Cancelling Requests

load requests will be automatically cancelled if the associated View is detached, the associated Lifecycle is destroyed, or another request is started on the same View.

Furthermore, each load request returns a RequestDisposable, which can be used to check if a request is in flight or dispose the request (effectively cancelling it and freeing its associated resources):

val disposable = imageView.load("")

// Cancel the request.

get requests will only be cancelled if the coroutine context's job is cancelled.

Image Sampling

Suppose you have an image that is 500x500 on disk, but you only need to load it into memory at 100x100 to be displayed in a view. Coil will load the image into memory, but what happens now if you need the image at 500x500? There's still more "quality" to read from disk, but the image is already loaded into memory at 100x100. Ideally, we would use the 100x100 image as a placeholder while we read the image from disk at 500x500.

This is exactly what Coil does and Coil handles this process automatically for all BitmapDrawables. Paired with crossfade(true), this can create a visual effect where the image detail appears to fade in, similar to a progressive JPEG.

Here's what it looks like in the sample app:

Images in the list have intentionally been loaded with very low detail and the crossfade is slowed down to highlight the visual effect.

Bitmap Pooling

Similar to Glide and Fresco, Coil supports bitmap pooling. Bitmap pooling is a technique to re-use Bitmap objects once they are no longer in use (i.e. when a View is detached, a Fragment's view is destroyed, etc.). This can significantly improve memory performance (especially on pre-Oreo devices), however it creates several API limitations.

To make this optimization as seamless and transparent to the consumer as possible, Targets must opt-in to bitmap pooling. To opt in, implement PoolableViewTarget; this requires the target to release all references to its current Drawable when its next lifecycle method is called.

See PoolableViewTarget for more information.


Do not use ImageView.getDrawable if the ImageView's Drawable has been set through Coil's ImageViewTarget. Instead, either load the image using a custom Target or copy underlying Bitmap using Bitmap.copy.