Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions coil-base/api/coil-base.api
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,10 @@ public final class coil/ImageLoader$Companion {
public final fun create (Landroid/content/Context;)Lcoil/ImageLoader;
}

public final class coil/ImageLoaders {
public static final fun executeBlocking (Lcoil/ImageLoader;Lcoil/request/ImageRequest;)Lcoil/request/ImageResult;
}

public abstract interface annotation class coil/annotation/ExperimentalCoilApi : java/lang/annotation/Annotation {
}

Expand Down
19 changes: 19 additions & 0 deletions coil-base/src/main/java/coil/ImageLoaders.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
@file:JvmName("ImageLoaders")
@file:Suppress("unused")

package coil

import androidx.annotation.WorkerThread
import coil.request.ImageRequest
import coil.request.ImageResult
import kotlinx.coroutines.runBlocking

/**
* Execute the [request] and block the current thread until it completes.
*
* @see ImageLoader.execute
*/
@WorkerThread
fun ImageLoader.executeBlocking(request: ImageRequest): ImageResult {
return runBlocking { execute(request) }
}
14 changes: 7 additions & 7 deletions coil-singleton/src/main/java/coil/Coil.kt
Original file line number Diff line number Diff line change
Expand Up @@ -10,21 +10,21 @@ import coil.request.ImageRequest
import coil.request.ImageResult

/**
* A singleton that holds the default [ImageLoader] instance.
* A class that holds the singleton [ImageLoader] instance.
*/
object Coil {

private var imageLoader: ImageLoader? = null
private var imageLoaderFactory: ImageLoaderFactory? = null

/**
* Get the default [ImageLoader]. Creates a new instance if none has been set.
* Get the singleton [ImageLoader]. Creates a new instance if none has been set.
*/
@JvmStatic
fun imageLoader(context: Context): ImageLoader = imageLoader ?: newImageLoader(context)

/**
* Convenience function to get the default [ImageLoader] and enqueue the [request].
* Convenience function to get the singleton [ImageLoader] and enqueue the [request].
*
* @see ImageLoader.enqueue
*/
Expand All @@ -34,7 +34,7 @@ object Coil {
}

/**
* Convenience function to get the default [ImageLoader] and execute the [request].
* Convenience function to get the singleton [ImageLoader] and execute the [request].
*
* @see ImageLoader.execute
*/
Expand All @@ -44,7 +44,7 @@ object Coil {
}

/**
* Set the default [ImageLoader]. Prefer using `setImageLoader(ImageLoaderFactory)`
* Set the singleton [ImageLoader]. Prefer using `setImageLoader(ImageLoaderFactory)`
* to create the [ImageLoader] lazily.
*/
@JvmStatic
Expand All @@ -55,7 +55,7 @@ object Coil {
}

/**
* Set the [ImageLoaderFactory] that will be used to create the default [ImageLoader].
* Set the [ImageLoaderFactory] that will be used to create the singleton [ImageLoader].
* The [factory] is guaranteed to be called at most once.
*
* NOTE: [factory] will take precedence over an [Application] that implements [ImageLoaderFactory].
Expand All @@ -67,7 +67,7 @@ object Coil {
imageLoader = null
}

/** Create and set the new default [ImageLoader]. */
/** Create and set the new singleton [ImageLoader]. */
@Synchronized
private fun newImageLoader(context: Context): ImageLoader {
// Check again in case imageLoader was just set.
Expand Down
2 changes: 1 addition & 1 deletion coil-singleton/src/main/java/coil/Contexts.kt
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ package coil
import android.content.Context

/**
* Get the default [ImageLoader]. This is an alias for [Coil.imageLoader].
* Get the singleton [ImageLoader]. This is an alias for [Coil.imageLoader].
*/
inline val Context.imageLoader: ImageLoader
@JvmName("imageLoader") get() = Coil.imageLoader(this)
2 changes: 1 addition & 1 deletion coil-singleton/src/main/java/coil/ImageLoaderFactory.kt
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import android.app.Application
/**
* A factory that creates new [ImageLoader] instances.
*
* To configure how the default [ImageLoader] is created **either**:
* To configure how the singleton [ImageLoader] is created **either**:
* - Implement [ImageLoaderFactory] in your [Application].
* - **Or** call [Coil.setImageLoader] with your [ImageLoaderFactory].
*/
Expand Down
4 changes: 2 additions & 2 deletions docs/getting_started.md
Original file line number Diff line number Diff line change
Expand Up @@ -128,13 +128,13 @@ val imageLoader = ImageLoader.Builder(context)
Coil.setImageLoader(imageLoader)
```

The default `ImageLoader` can be retrieved using an extension function on `Context`:
The singleton `ImageLoader` can be retrieved using the `Context.imageLoader` extension function:

```kotlin
val imageLoader = context.imageLoader
```

Setting a default `ImageLoader` is optional. If you don't set one, Coil will lazily create an `ImageLoader` with the default values.
Setting the singleton `ImageLoader` is optional. If you don't set one, Coil will lazily create an `ImageLoader` with the default values.

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](../image_loaders/#singleton-vs-dependency-injection).

Expand Down
2 changes: 1 addition & 1 deletion docs/image_loaders.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ Coil performs best when you create a single `ImageLoader` and share it throughou

If you use a dependency injector like [Dagger](https://github.com/google/dagger), then you should create a single `ImageLoader` instance and inject it throughout your app.

However, if you'd prefer a singleton the `io.coil-kt:coil` artifact provides a default `ImageLoader` instance that can be accessed using the extension function `context.imageLoader`. [Read here](../getting_started/#singleton) for how to initialize the singleton `ImageLoader` instance.
However, if you'd prefer a singleton the `io.coil-kt:coil` artifact provides a singleton `ImageLoader` instance that can be accessed using the `Context.imageLoader` extension function. [Read here](../getting_started/#singleton) for how to initialize the singleton `ImageLoader` instance.

!!! Note
Use the `io.coil-kt:coil-base` artifact if you are using dependency injection.
Expand Down
21 changes: 8 additions & 13 deletions docs/java_compatibility.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,13 @@ Coil's API is designed to be Kotlin-first. It leverages Kotlin language features

Importantly, suspend functions cannot be implemented in Java. This means custom [Transformations](transformations.md), [Size Resolvers](../api/coil-base/coil.size/-size-resolver), [Fetchers](../image_pipeline/#fetchers), and [Decoders](../image_pipeline/#decoders) **must** be implemented in Kotlin.

Despite these limitations, most of Coil's API is Java compatible. For instance, the syntax to enqueue an `ImageRequest` is almost the same in Java and Kotlin:
Despite these limitations, most of Coil's API is Java compatible. The `Context.imageLoader` extension function should not be used from Java. Instead, you can get the singleton `ImageLoader` using:

```java
ImageLoader imageLoader = Coil.imageLoader(context)
```

The syntax to enqueue an `ImageRequest` is almost the same in Java and Kotlin:

```java
ImageRequest request = new ImageRequest.Builder(context)
Expand All @@ -18,18 +24,7 @@ imageLoader.enqueue(request)
!!! Note
`ImageView.load` extension functions cannot be used from Java. Use the `ImageRequest.Builder` API instead.

`suspend` functions cannot be easily called from Java. Thus, to get an image synchronously you'll have to create a wrapper function to `execute` an `ImageRequest`:

```kotlin
@file:JvmName("ImageLoaders")

@WorkerThread
fun ImageLoader.executeBlocking(request: ImageRequest): ImageResult {
return runBlocking { execute(request) }
}
```

Then call the `ImageLoaders` function from Java:
`suspend` functions cannot be easily called from Java. Thus, to get an image synchronously you'll have to use the `ImageLoader.executeBlocking` extension function which can be called from Java like so:

```java
ImageRequest request = ImageRequest.builder(context)
Expand Down