Skip to content

Commit

Permalink
Add ImageLoader parameter
Browse files Browse the repository at this point in the history
Closes #79
  • Loading branch information
Chris Banes committed Sep 16, 2020
1 parent 4b5e39b commit a7bb940
Show file tree
Hide file tree
Showing 6 changed files with 64 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -80,4 +80,5 @@ object Libs {
const val coil = "io.coil-kt:coil:1.0.0-rc1"

const val truth = "com.google.truth:truth:1.0.1"
const val mockk = "io.mockk:mockk-android:1.10.0"
}
8 changes: 4 additions & 4 deletions coil/api/coil.api
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
public final class dev/chrisbanes/accompanist/coil/CoilImage {
public static final fun CoilImage (Lcoil/request/ImageRequest;Landroidx/compose/ui/Modifier;Landroidx/compose/ui/Alignment;Landroidx/compose/ui/layout/ContentScale;Landroidx/compose/ui/graphics/ColorFilter;Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function1;Landroidx/compose/runtime/Composer;II)V
public static final fun CoilImage (Ljava/lang/Object;Landroidx/compose/ui/Modifier;Landroidx/compose/ui/Alignment;Landroidx/compose/ui/layout/ContentScale;Landroidx/compose/ui/graphics/ColorFilter;Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function1;Landroidx/compose/runtime/Composer;II)V
public static final fun CoilImageWithCrossfade (Lcoil/request/ImageRequest;Landroidx/compose/ui/Modifier;Landroidx/compose/ui/Alignment;Landroidx/compose/ui/layout/ContentScale;ILkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function1;Landroidx/compose/runtime/Composer;II)V
public static final fun CoilImageWithCrossfade (Ljava/lang/Object;Landroidx/compose/ui/Modifier;Landroidx/compose/ui/Alignment;Landroidx/compose/ui/layout/ContentScale;ILkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function1;Landroidx/compose/runtime/Composer;II)V
public static final fun CoilImage (Lcoil/request/ImageRequest;Landroidx/compose/ui/Modifier;Landroidx/compose/ui/Alignment;Landroidx/compose/ui/layout/ContentScale;Landroidx/compose/ui/graphics/ColorFilter;Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function2;Lcoil/ImageLoader;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function1;Landroidx/compose/runtime/Composer;II)V
public static final fun CoilImage (Ljava/lang/Object;Landroidx/compose/ui/Modifier;Landroidx/compose/ui/Alignment;Landroidx/compose/ui/layout/ContentScale;Landroidx/compose/ui/graphics/ColorFilter;Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function2;Lcoil/ImageLoader;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function1;Landroidx/compose/runtime/Composer;II)V
public static final fun CoilImageWithCrossfade (Lcoil/request/ImageRequest;Landroidx/compose/ui/Modifier;Landroidx/compose/ui/Alignment;Landroidx/compose/ui/layout/ContentScale;ILkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function2;Lcoil/ImageLoader;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function1;Landroidx/compose/runtime/Composer;II)V
public static final fun CoilImageWithCrossfade (Ljava/lang/Object;Landroidx/compose/ui/Modifier;Landroidx/compose/ui/Alignment;Landroidx/compose/ui/layout/ContentScale;ILkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function2;Lcoil/ImageLoader;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function1;Landroidx/compose/runtime/Composer;II)V
}

public final class dev/chrisbanes/accompanist/coil/ErrorResult : dev/chrisbanes/accompanist/coil/RequestResult {
Expand Down
1 change: 1 addition & 0 deletions coil/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ dependencies {

androidTestImplementation Libs.junit
androidTestImplementation Libs.truth
androidTestImplementation Libs.mockk

androidTestImplementation Libs.Coroutines.test

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import androidx.compose.ui.unit.dp
import androidx.core.net.toUri
import androidx.test.filters.LargeTest
import androidx.test.filters.SdkSuppress
import androidx.test.platform.app.InstrumentationRegistry
import androidx.ui.test.assertHeightIsAtLeast
import androidx.ui.test.assertHeightIsEqualTo
import androidx.ui.test.assertIsDisplayed
Expand All @@ -42,10 +43,15 @@ import androidx.ui.test.createComposeRule
import androidx.ui.test.onNodeWithTag
import androidx.ui.test.onNodeWithText
import androidx.ui.test.runOnIdle
import coil.EventListener
import coil.ImageLoader
import coil.annotation.ExperimentalCoilApi
import coil.request.CachePolicy
import coil.request.ImageRequest
import com.google.common.truth.Truth.assertThat
import dev.chrisbanes.accompanist.coil.test.R
import io.mockk.mockk
import io.mockk.verify
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.flow.MutableStateFlow
Expand Down Expand Up @@ -137,6 +143,35 @@ class CoilTest {
.assertPixels { Color.Red }
}

@OptIn(ExperimentalCoilApi::class)
@Test
fun basicLoad_customImageLoader() {
val context = InstrumentationRegistry.getInstrumentation().targetContext
val latch = CountDownLatch(1)

// Build a custom ImageLoader with a mocked EventListener
val eventListener = mockk<EventListener>(relaxed = true)
val imageLoader = ImageLoader.Builder(context)
.eventListener(eventListener)
.build()

composeTestRule.setContent {
CoilImage(
data = resourceUri(R.drawable.red_rectangle),
modifier = Modifier.preferredSize(128.dp, 128.dp),
imageLoader = imageLoader,
onRequestCompleted = { latch.countDown() }
)
}

// Wait for the onRequestCompleted to release the latch
latch.await(5, TimeUnit.SECONDS)

// Verify that our eventListener was invoked
verify(atLeast = 1) { eventListener.fetchStart(any(), any(), any()) }
verify(atLeast = 1) { eventListener.fetchEnd(any(), any(), any(), any()) }
}

@OptIn(ExperimentalCoroutinesApi::class)
@Test
@SdkSuppress(minSdkVersion = 26) // captureToBitmap is SDK 26+
Expand Down
15 changes: 13 additions & 2 deletions coil/src/main/java/dev/chrisbanes/accompanist/coil/Coil.kt
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ import androidx.compose.ui.platform.ContextAmbient
import androidx.compose.ui.unit.IntSize
import androidx.core.graphics.drawable.toBitmap
import coil.Coil
import coil.ImageLoader
import coil.decode.DataSource
import coil.request.ImageRequest
import coil.request.ImageResult
Expand All @@ -64,6 +65,8 @@ import coil.request.ImageResult
* @param getFailurePainter Optional builder for the [Painter] to be used to draw the failure
* loading result. Passing in `null` will result in falling back to the default [Painter].
* @param loading Content to be displayed when the request is in progress.
* @param imageLoader The [ImageLoader] to use when requesting the image. Defaults to [Coil]'s
* default image loader.
* @param shouldRefetchOnSizeChange Lambda which will be invoked when the size changes, allowing
* optional re-fetching of the image. Return true to re-fetch the image.
* @param onRequestCompleted Listener which will be called when the loading request has finished.
Expand All @@ -78,6 +81,7 @@ fun CoilImage(
getSuccessPainter: @Composable ((SuccessResult) -> Painter)? = null,
getFailurePainter: @Composable ((ErrorResult) -> Painter?)? = null,
loading: @Composable (() -> Unit)? = null,
imageLoader: ImageLoader = Coil.imageLoader(ContextAmbient.current),
shouldRefetchOnSizeChange: (currentResult: RequestResult, size: IntSize) -> Boolean = defaultRefetchOnSizeChangeLambda,
onRequestCompleted: (RequestResult) -> Unit = emptySuccessLambda
) {
Expand All @@ -99,6 +103,7 @@ fun CoilImage(
getSuccessPainter = getSuccessPainter,
getFailurePainter = getFailurePainter,
loading = loading,
imageLoader = imageLoader,
shouldRefetchOnSizeChange = shouldRefetchOnSizeChange,
modifier = modifier
)
Expand All @@ -121,6 +126,8 @@ fun CoilImage(
* @param getFailurePainter Optional builder for the [Painter] to be used to draw the failure
* loading result. Passing in `null` will result in falling back to the default [Painter].
* @param loading Content to be displayed when the request is in progress.
* @param imageLoader The [ImageLoader] to use when requesting the image. Defaults to [Coil]'s
* default image loader.
* @param shouldRefetchOnSizeChange Lambda which will be invoked when the size changes, allowing
* optional re-fetching of the image. Return true to re-fetch the image.
* @param onRequestCompleted Listener which will be called when the loading request has finished.
Expand All @@ -135,6 +142,7 @@ fun CoilImage(
getSuccessPainter: @Composable ((SuccessResult) -> Painter)? = null,
getFailurePainter: @Composable ((ErrorResult) -> Painter?)? = null,
loading: @Composable (() -> Unit)? = null,
imageLoader: ImageLoader = Coil.imageLoader(ContextAmbient.current),
shouldRefetchOnSizeChange: (currentResult: RequestResult, size: IntSize) -> Boolean = defaultRefetchOnSizeChangeLambda,
onRequestCompleted: (RequestResult) -> Unit = emptySuccessLambda
) {
Expand All @@ -153,7 +161,9 @@ fun CoilImage(
val callback = remember { mutableStateOf(onRequestCompleted, referentialEqualityPolicy()) }
callback.value = onRequestCompleted

val requestActor = remember(request) { CoilRequestActor(request) }
val requestActor = remember(imageLoader, request) {
CoilRequestActor(imageLoader, request)
}

launchInComposition(requestActor) {
// Launch the Actor
Expand Down Expand Up @@ -234,6 +244,7 @@ private const val UNSPECIFIED = -1
private data class MutableRef<T>(var value: T)

private fun CoilRequestActor(
imageLoader: ImageLoader,
request: ImageRequest
) = RequestActor<IntSize, RequestResult?> { size ->
when {
Expand All @@ -256,7 +267,7 @@ private fun CoilRequestActor(
}
}?.let { transformedRequest ->
// Now execute the request in Coil...
Coil.imageLoader(transformedRequest.context)
imageLoader
.execute(transformedRequest)
.toResult(size)
.also {
Expand Down
10 changes: 10 additions & 0 deletions coil/src/main/java/dev/chrisbanes/accompanist/coil/Crossfade.kt
Original file line number Diff line number Diff line change
Expand Up @@ -42,11 +42,13 @@ import androidx.compose.ui.graphics.drawscope.drawCanvas
import androidx.compose.ui.graphics.painter.Painter
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.platform.AnimationClockAmbient
import androidx.compose.ui.platform.ContextAmbient
import androidx.compose.ui.unit.IntOffset
import androidx.compose.ui.unit.IntSize
import androidx.compose.ui.unit.toSize
import androidx.core.util.Pools
import coil.Coil
import coil.ImageLoader
import coil.decode.DataSource
import coil.request.ImageRequest

Expand All @@ -69,6 +71,8 @@ private const val DefaultTransitionDuration = 1000
* @param crossfadeDuration The duration of the crossfade animation in milliseconds.
* @param getFailurePainter Optional builder for the [Painter] to be used to draw the failure
* loading result. Passing in `null` will result in falling back to the default [Painter].
* @param imageLoader The [ImageLoader] to use when requesting the image. Defaults to [Coil]'s
* default image loader.
* @param shouldRefetchOnSizeChange Lambda which will be invoked when the size changes, allowing
* optional re-fetching of the image. Return true to re-fetch the image.
* @param onRequestCompleted Listener which will be called when the loading request has finished.
Expand All @@ -82,6 +86,7 @@ fun CoilImageWithCrossfade(
crossfadeDuration: Int = DefaultTransitionDuration,
getFailurePainter: @Composable ((ErrorResult) -> Painter?)? = null,
loading: @Composable (() -> Unit)? = null,
imageLoader: ImageLoader = Coil.imageLoader(ContextAmbient.current),
shouldRefetchOnSizeChange: (currentResult: RequestResult, size: IntSize) -> Boolean = defaultRefetchOnSizeChangeLambda,
onRequestCompleted: (RequestResult) -> Unit = emptySuccessLambda
) {
Expand All @@ -93,6 +98,7 @@ fun CoilImageWithCrossfade(
getFailurePainter = getFailurePainter,
loading = loading,
modifier = modifier,
imageLoader = imageLoader,
shouldRefetchOnSizeChange = shouldRefetchOnSizeChange,
onRequestCompleted = onRequestCompleted
)
Expand All @@ -116,6 +122,8 @@ fun CoilImageWithCrossfade(
* @param crossfadeDuration The duration of the crossfade animation in milliseconds.
* @param getFailurePainter Optional builder for the [Painter] to be used to draw the failure
* loading result. Passing in `null` will result in falling back to the default [Painter].
* @param imageLoader The [ImageLoader] to use when requesting the image. Defaults to [Coil]'s
* default image loader.
* @param shouldRefetchOnSizeChange Lambda which will be invoked when the size changes, allowing
* optional re-fetching of the image. Return true to re-fetch the image.
* @param onRequestCompleted Listener which will be called when the loading request has finished.
Expand All @@ -129,6 +137,7 @@ fun CoilImageWithCrossfade(
crossfadeDuration: Int = DefaultTransitionDuration,
getFailurePainter: @Composable ((ErrorResult) -> Painter?)? = null,
loading: @Composable (() -> Unit)? = null,
imageLoader: ImageLoader = Coil.imageLoader(ContextAmbient.current),
shouldRefetchOnSizeChange: (currentResult: RequestResult, size: IntSize) -> Boolean = defaultRefetchOnSizeChangeLambda,
onRequestCompleted: (RequestResult) -> Unit = emptySuccessLambda
) {
Expand All @@ -139,6 +148,7 @@ fun CoilImageWithCrossfade(
getSuccessPainter = { crossfadePainter(it, durationMs = crossfadeDuration) },
getFailurePainter = getFailurePainter,
loading = loading,
imageLoader = imageLoader,
shouldRefetchOnSizeChange = shouldRefetchOnSizeChange,
modifier = modifier,
onRequestCompleted = onRequestCompleted
Expand Down

0 comments on commit a7bb940

Please sign in to comment.