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
相关产品推荐
相关产品推荐

