如何在 Jetpack Compose 的新线圈版本中使用 `ImageRequest.Builder.target`?

How to use `ImageRequest.Builder.target` in the new coil version in jetpack compose?

我的Gradle

// Coil
implementation "io.coil-kt:coil-compose:1.4.0"

问题描述

以前我将线圈与 Google 的 accompanist 一起使用,但是当我迁移到新版本的线圈时 as the documentation suggests 我遇到了 target方法:

E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.example.pokedex, PID: 13502
    java.lang.IllegalArgumentException: request.target must be null.
        at coil.compose.ImagePainterKt.rememberImagePainter(ImagePainter.kt:94)
...

线圈实现

在浏览ImagePainter(线圈class)的内部代码时可以看到target方法确实需要为null,因为某些原因:

@Composable
fun rememberImagePainter(
     request: ImageRequest,
     imageLoader: ImageLoader,
     onExecute: ExecuteCallback = ExecuteCallback.Default,
): ImagePainter {
     requireSupportedData(request.data)
     require(request.target == null) { "request.target must be null." }
...

我的代码

这是我在 jetpack compose 中的组件(图像组件在一列内):

Image(
    modifier = Modifier
        .size(120.dp)
        .align(Alignment.CenterHorizontally),
    painter = rememberImagePainter(
        data = entry.imageUrl,
        builder = {
            crossfade(true)
            target {
                viewModel.calcDominantColor(it) { color ->
                    dominantColor = color
                }
            }
            transformations(CircleCropTransformation())
        },
    ),
    contentDescription = entry.pokemonName
)

我需要目标方法根据它作为参数传递的 drawable 对我的 viewModel 进行内部操作。有人可以帮助我吗?

在Coil 2.0.0AsyncImagerememberAsyncImagePainter都有onSuccess回调参数,使用它你可以得到drawable如下:

AsyncImage(
    model = imageURL,
    contentDescription = null,
    onSuccess = { success ->
        val drawable = success.result.drawable
    }
)

线圈1.4.0版本:

这是预期的行为,因为 rememberImagePainter 在内部设置了 target

您可以跟踪画家状态,等待 Success 并从中获取 drawable。还可以将它与 LaunchedEffect 一起使用以防止重新计算:

val painter = rememberImagePainter(
    data = imageUrl,
    builder = {
        ...
    },
)
(painter.state as? ImagePainter.State.Success)
    ?.let { successState ->
        LaunchedEffect(Unit) {
            val drawable = successState.result.drawable
            viewModel.calcDominantColor(drawable) { color ->
                dominantColor = color
            }
        }
    }
Image(
    painter = painter,
    contentDescription = "...",
    modifier = Modifier
        ...
)