coil-kt/coil
View on GitHubCoil3 with Compose | Issue using rememberAsyncImagePainter with multiple @Preview
Open
#3001 opened on May 29, 2025
help wanted
Description
Describe the bug
As shown in the image below, using rememberAsyncImagePainter doesn't seem to prompt all the necessary previews when combined with multiple @Preview.
It also seems to show the preview is out of date, even after rebuilding, also that might just be a red herring.
To Reproduce Here is a sample code to reproduce the issue presented above using sample code from the documentation available here.
package com.stash.android.sds.compose.components.content.test
import android.content.res.Configuration
import androidx.compose.foundation.Image
import androidx.compose.material.CircularProgressIndicator
import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.toArgb
import androidx.compose.ui.tooling.preview.Devices
import androidx.compose.ui.tooling.preview.Preview
import coil3.ColorImage
import coil3.annotation.ExperimentalCoilApi
import coil3.compose.AsyncImagePainter
import coil3.compose.AsyncImagePreviewHandler
import coil3.compose.LocalAsyncImagePreviewHandler
import coil3.compose.rememberAsyncImagePainter
@OptIn(ExperimentalCoilApi::class)
@Composable
internal fun CoilPreviewBug(
) {
val previewHandler = AsyncImagePreviewHandler { ColorImage(Color.Red.toArgb()) }
CompositionLocalProvider(
LocalAsyncImagePreviewHandler provides previewHandler,
) {
val painter = rememberAsyncImagePainter("https://example.com/image.jpg")
val state by painter.state.collectAsState()
when (state) {
is AsyncImagePainter.State.Empty,
is AsyncImagePainter.State.Loading -> {
CircularProgressIndicator()
}
is AsyncImagePainter.State.Success -> {
Image(
painter = painter,
contentDescription = null,
)
}
is AsyncImagePainter.State.Error -> {
// Show some error UI.
}
}
}
}
@Composable
@Preview(name = "1 - Light Mode", device = Devices.PIXEL_4_XL)
@Preview(name = "2 - Dark Mode", uiMode = Configuration.UI_MODE_NIGHT_YES, device = Devices.PIXEL_4_XL)
@Preview(name = "3 - Light Mode - Large", device = Devices.PIXEL_4_XL, fontScale = 2.0f)
internal fun CoilPreviewBugPreview() {
CoilPreviewBug()
}
As a side note, I was able to show all previews using the code below. However, I am unsure if the way I set up my code is the recommended approach. I would have expected rememberAsyncImagePainter to work with any number of previews.
val previewHandler = AsyncImagePreviewHandler { ColorImage(Color.Red.toArgb()) }
CompositionLocalProvider(
LocalAsyncImagePreviewHandler provides AsyncImagePreviewHandler { previewHandler },
) {
val painter = rememberAsyncImagePainter(
model = ImageRequest.Builder(LocalPlatformContext.current)
.data("https://example.com/image.jpg")
.build(),
)
val state by painter.state.collectAsState()
if (LocalInspectionMode.current) {
Image(
painter = painter,
contentDescription = null,
)
} else if (state is AsyncImagePainter.State.Success || state is AsyncImagePainter.State.Error) {
Image(
painter = painter,
contentDescription = null,
)
} else {
CircularProgressIndicator()
}
}
Version
coilCompose = "3.2.0"
coilCompose = { module = "io.coil-kt.coil3:coil-compose", version.ref = "coilCompose" }
coilNetworkOkhttp = { module = "io.coil-kt.coil3:coil-network-okhttp", version.ref = "coilCompose" }
coilSvg = { module = "io.coil-kt.coil3:coil-svg", version.ref = "coilCompose" }