coil-kt/coil

Coil3 with Compose | Issue using rememberAsyncImagePainter with multiple @Preview

Open

#3,001 创建于 2025年5月29日

在 GitHub 查看
 (4 评论) (0 反应) (0 负责人)Kotlin (757 fork)batch import
help wanted

仓库指标

Star
 (11,779 star)
PR 合并指标
 (平均合并 20小时 14分钟) (30 天内合并 28 个 PR)

描述

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.

Image

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" }

贡献者指南