2

I recently migrated from Accompanist's ImagePainter to Coil's, below is the pertinent code after my updates.

val painter = rememberImagePainter(DRAWABLE_RESOURCE_ID)

when (painter.state) {
    is ImagePainter.State.Empty -> Timber.w("Empty")
    is ImagePainter.State.Loading -> {
        Box(
            contentAlignment = Alignment.Center,
            modifier = Modifier.wrapContentSize()
        ) {
            CircularProgressIndicator()
        }
    }
    is ImagePainter.State.Success -> {
        Image(
            painter = painter,
            contentDescription = null,
            contentScale = ContentScale.Fit,
            modifier = Modifier
                .padding(8.dp)
                .size(84.dp)
                .clip(RoundedCornerShape(corner = CornerSize(16.dp)))
        )
    }
    is ImagePainter.State.Error -> Timber.e("Error")
}

Now those images don't render and painter.state is always Empty. My legacy Accompanist implementation displayed images by this point in the code. It also works if I use the stock painterResource(resId) from Compose.

What am I missing to execute Coil's new painter through its states?

es0329
  • 1,366
  • 1
  • 18
  • 35

4 Answers4

5

You can use the drawable's resource ID as model for the coil's AsyncImage composable.

AsyncImage(
    model = R.drawable.bg_gradient,
    contentDescription = "Gradient background",
)

There's a significant performance difference between the composables - Image and AsyncImage. So Coil's AsyncImage loading is very handy at times.

Roshan
  • 369
  • 4
  • 9
3

You don't need coil to load local resources. You can use system painterResource:

Image(
    painter = painterResource(id = R.drawable.test),
    contentDescription = null,
    contentScale = ContentScale.Fit,
    modifier = Modifier
        .padding(8.dp)
        .size(84.dp)
        .clip(RoundedCornerShape(corner = CornerSize(16.dp)))
)

If you would use it for remove image loading: since move from accompanist to coil, painter won't start loading unless Image is in the view tree hierarchy. So you can move Image into a Box with your while:

Box(contentAlignment = Alignment.Center) {
    val painter = rememberImagePainter(R.drawable.test)
    Image(
        painter = painter,
        contentDescription = null,
        contentScale = ContentScale.Fit,
        modifier = Modifier
            .padding(8.dp)
            .size(84.dp)
            .clip(RoundedCornerShape(corner = CornerSize(16.dp)))
    )
    when (painter.state) {
        is ImagePainter.State.Empty -> Timber.w("Empty")
        is ImagePainter.State.Loading -> {
            Box(
                contentAlignment = Alignment.Center,
                modifier = Modifier.wrapContentSize()
            ) {
                CircularProgressIndicator()
            }
        }
        is ImagePainter.State.Success -> {

        }
        is ImagePainter.State.Error -> Timber.e("Error")
    }
}

Also it may not start loading when you're not providing enough size modifiers(that's not your case, just for you to know). Check out this answer for more information.

Phil Dukhov
  • 67,741
  • 15
  • 184
  • 220
3

As suggested by @Philip Dukhov you don't need coil to load local resources.

If you want to use it, you can simply your code using:

val painter = rememberImagePainter(R.drawable.xxx)
val state = painter.state
Box(
    contentAlignment = Alignment.Center,
    modifier = Modifier.wrapContentSize()
) {
    AnimatedVisibility(visible = (state is ImagePainter.State.Loading)) {
        CircularProgressIndicator()
    }
    Image(
        painter = painter,
        contentDescription = null,
        modifier = Modifier.size(128.dp)
    )
}

enter image description here

Gabriele Mariotti
  • 320,139
  • 94
  • 887
  • 841
0
val context = LocalContext.current
val imageLoader = ImageLoader(context)

val request = ImageRequest.Builder(context)
        .data(thumbnailUrl)
        .build()

val painter = rememberImagePainter(
        request = request,
        imageLoader = imageLoader
    )

val state = painter.state

Image(
  painter = painter,
  contentDescription = "thumbnail image",
  modifier = Modifier
            .fillMaxSize()
            .placeholder(
                visible = state is ImagePainter.State.Loading,
                color = PlaceholderDefaults.color(
                    backgroundColor = SMXTheme.colors.shimmer.copy(0.1f),
                ),
                highlight = PlaceholderHighlight.shimmer(),
            ),
        contentScale = ContentScale.Crop
    )
svg
  • 114
  • 1
  • 8