You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Coil rememberAsyncImagePainter状态未更新引发无限Shimmer动画问题

解决Coil AsyncImagePainter无限Shimmer动画问题

问题原因

你的代码中,当AsyncImagePainter处于Loading状态时,没有渲染Image组件。而AsyncImagePainter需要被Compose组合(即Image被绘制)才能驱动图片加载流程、完成状态切换。如果始终不渲染Image,加载流程无法推进,状态会一直停留在Loading,导致Shimmer无限循环。

修复方案

方案1:使用AsyncImage组件(推荐)

Coil提供的AsyncImage已封装状态处理逻辑,直接通过参数设置Shimmer即可,无需手动管理状态:

@Composable
fun FoodItem(food: Fun) {
    Column(
        modifier = Modifier.fillMaxWidth(),
        horizontalAlignment = Alignment.Start,
        verticalArrangement = Arrangement.Top
    ) {
        AsyncImage(
            model = food.image.sm,
            contentDescription = "Food photo",
            modifier = Modifier
                .fillMaxWidth()
                .height(104.dp)
                .clip(RoundedCornerShape(8.dp)),
            contentScale = ContentScale.Crop,
            // 加载中显示Shimmer
            onLoading = {
                AnimatedShimmer { brush ->
                    ShimmerFoodItem(brush = brush)
                }
            },
            error = painterResource(R.drawable.error_drawable)
        )
        // 下方文本保持不变
        Text(
            modifier = Modifier.padding(top = 4.dp),
            text = food.title,
            fontSize = MaterialTheme.typography.body1.fontSize,
            overflow = TextOverflow.Ellipsis,
            maxLines = 1,
            fontWeight = FontWeight.Bold
        )
        Text(
            text = food.subtitle,
            fontSize = MaterialTheme.typography.subtitle2.fontSize,
            overflow = TextOverflow.Ellipsis,
            maxLines = 2,
            fontWeight = FontWeight.Normal
        )
    }
}

方案2:手动管理AsyncImagePainter状态(保留原结构)

如果坚持使用AsyncImagePainter,需确保始终渲染Image,通过状态控制Shimmer的显示:

@Composable
fun FoodItem(food: Fun) {
    Column(
        modifier = Modifier.fillMaxWidth(),
        horizontalAlignment = Alignment.Start,
        verticalArrangement = Arrangement.Top
    ) {
        val painter = rememberAsyncImagePainter(food.image.sm)
        val isLoading = painter.state is AsyncImagePainter.State.Loading

        Box(modifier = Modifier.fillMaxWidth().height(104.dp)) {
            Image(
                modifier = Modifier
                    .fillMaxWidth()
                    .height(104.dp)
                    .clip(RoundedCornerShape(8.dp)),
                painter = painter,
                contentScale = ContentScale.Crop,
                contentDescription = "Food photo"
            )
            // 加载中时显示Shimmer覆盖在Image上
            if (isLoading) {
                AnimatedShimmer { ShimmerFoodItem(brush = it) }
            }
        }

        // 下方文本保持不变
        Text(
            modifier = Modifier.padding(top = 4.dp),
            text = food.title,
            fontSize = MaterialTheme.typography.body1.fontSize,
            overflow = TextOverflow.Ellipsis,
            maxLines = 1,
            fontWeight = FontWeight.Bold
        )
        Text(
            text = food.subtitle,
            fontSize = MaterialTheme.typography.subtitle2.fontSize,
            overflow = TextOverflow.Ellipsis,
            maxLines = 2,
            fontWeight = FontWeight.Normal
        )
    }
}

关键说明

  • 方案1利用Coil封装好的AsyncImage,减少手动状态管理的出错概率,是官方推荐用法。
  • 方案2中Image始终被组合,确保AsyncImagePainter能正常推进加载流程,状态切换后Shimmer会自动隐藏。

内容的提问来源于stack exchange,提问作者qveex

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.17 03:35:21