求助: Compose开发多图片列表时遇到严重卡顿问题

单Card中图片越多卡顿越严重,用的是Column,用LazyColumn卡顿更严重

Column卡顿表现为低帧率,LazyColumn则是掉帧+低帧率(因为划出界面就重组)\

图片为使用Column现象

用的Coil库加载图片,然后异步显示

不知道是不是因为组件嵌套过多的问题,但是如果不嵌套的话该如何在同一个Card中显示多个图片?求大佬帮助\

卡片部分

kotlin 复制代码
    @Composable
    fun ContentSection(
        modifier: Modifier,
        text: String?,
        location: LocationData?,
        date: Date?,
        expanded: Boolean,
        onExpandClick: () -> Unit,
        textLayoutResult: MutableState<TextLayoutResult?>
    ) {
        Column(
            modifier = Modifier.padding(bottom = 8.dp)
        ) {
            if (text != null) {
                val textStyle = MaterialTheme.typography.bodyMedium
                Text(
                    text = text,
                    style = textStyle,
                    maxLines = if (expanded) Int.MAX_VALUE else 6,
                    overflow = TextOverflow.Ellipsis,
                    modifier = Modifier
                        .padding(16.dp)
                        .clickable(onClick = onExpandClick),
                    onTextLayout = { textLayoutResult.value = it }
                )
            }

            if (location != null) {
                LocationInfo(location)
            }

            if (date != null) {
                DateInfo(date)
            }
        }
    }

    @SuppressLint("MutableCollectionMutableState")
    @Composable
    fun JournalCard(modifier: Modifier, journalData: JournalData) {
        // 控制文本展开状态
        val (expanded, setExpanded) = remember { mutableStateOf(false) }
        val textLayoutResult = remember { mutableStateOf<TextLayoutResult?>(null) }

        // 添加图片预览状态
        val (showImagePreview, setShowImagePreview) = remember { mutableStateOf(false) }
        val (selectedImageIndex, setSelectedImageIndex) = remember { mutableIntStateOf(0) }
        val journalDataRem = remember { mutableStateOf(journalData) }
        ElevatedCard(
            colors = CardDefaults.elevatedCardColors(
                containerColor = MaterialTheme.colorScheme.surfaceVariant,
                contentColor = MaterialTheme.colorScheme.onSurfaceVariant
            ),
            elevation = CardDefaults.cardElevation(defaultElevation = 8.dp),
            modifier = modifier
                .fillMaxWidth()
    //            .padding(horizontal = 16.dp, vertical = 12.dp)
    //            .animateContentSize()
        ) {
            Column {
                // 图片区域
                ImageSection(
                    modifier = modifier,
                    images = journalDataRem.value.images,
                    onImageClick = { index ->
                        setSelectedImageIndex(index)
                        setShowImagePreview(true)
                    }
                )

                // 内容区域
                ContentSection(
                    modifier = modifier,
                    text = journalDataRem.value.text,
                    location = journalDataRem.value.location,
                    date = journalDataRem.value.date,
                    expanded = expanded,
                    onExpandClick = { setExpanded(!expanded) },
                    textLayoutResult = textLayoutResult
                )
            }
        }

        // 显示图片预览
        if (showImagePreview && !journalDataRem.value.images.isNullOrEmpty()) {
            ImageGalleryPreview(
                images = journalDataRem.value.images!!,
                initialIndex = selectedImageIndex,
                onDismiss = { setShowImagePreview(false) }
            )
        }
    }

以下为图片加载部分

kotlin 复制代码
    @Composable
    fun SingleImage(image: Bitmap, onImageClick: (Int) -> Unit) {

        AsyncImage(
            model = ImageRequest.Builder(LocalContext.current)
                .data(image)
                .memoryCachePolicy(CachePolicy.ENABLED)
                .diskCachePolicy(CachePolicy.ENABLED)
                .crossfade(true)
                .size(200) // 增加缩略图尺寸以提高质量
                .build(),
    //        imageLoader = ImageLoadUtils.getImageLoader(),
            contentDescription = "Journal Image",
            contentScale = ContentScale.Crop,
            modifier = Modifier
                .fillMaxSize()
                .clickable { onImageClick(0) },
            clipToBounds = true
        )
    }

    @Composable
    fun TwoImages(images: MutableList<Bitmap>, onImageClick: (Int) -> Unit) {
        Row(modifier = Modifier.fillMaxSize()) {
            Box(
                modifier = Modifier
                    .weight(1f)
                    .fillMaxHeight()
                    .padding(end = 2.dp)
                    .clip(RoundedCornerShape(12.dp))
                    .clickable { onImageClick(0) }
            ) {
                AsyncImage(
                    model =  images[0],
                    contentDescription = "Journal Image 1",
                    contentScale = ContentScale.Crop,
                    imageLoader = ImageLoadUtils.getImageLoader(),
                    modifier = Modifier.fillMaxSize(),
                    clipToBounds = true
                )
            }

            Box(
                modifier = Modifier
                    .weight(1f)
                    .fillMaxHeight()
                    .padding(start = 2.dp)
                    .clip(RoundedCornerShape(12.dp))
                    .clickable { onImageClick(1) }
            ) {
                AsyncImage(
                    model = images[1],
                    contentDescription = "Journal Image 2",
                    contentScale = ContentScale.Crop,
                    imageLoader = ImageLoadUtils.getImageLoader(),
                    modifier = Modifier.fillMaxSize(),
                    clipToBounds = true
                )
            }
        }
    }

    @Composable
    fun ThreeImages(images: MutableList<Bitmap>, onImageClick: (Int) -> Unit) {
        Row(modifier = Modifier.fillMaxSize()) {
            Box(
                modifier = Modifier
                    .weight(0.5f)
                    .fillMaxHeight()
                    .padding(end = 4.dp)
                    .clip(RoundedCornerShape(12.dp))
                    .clickable { onImageClick(0) }
            ) {
                AsyncImage(
                    model = ImageRequest.Builder(LocalContext.current)
                        .data(images[0])
                        .memoryCachePolicy(CachePolicy.ENABLED)
                        .diskCachePolicy(CachePolicy.ENABLED)
                        .crossfade(true)
                        .size(150) // 设置缩略图尺寸
                        .build(),
                    contentDescription = "Journal Image 1",
                    contentScale = ContentScale.Crop,
                    modifier = Modifier.fillMaxSize(),
                    clipToBounds = true
                )
            }

            Column(
                modifier = Modifier
                    .weight(0.5f)
                    .fillMaxHeight(),
                verticalArrangement = Arrangement.spacedBy(4.dp)
            ) {
                Box(
                    modifier = Modifier
                        .weight(0.5f)
                        .fillMaxWidth()
                        .clip(RoundedCornerShape(12.dp))
                        .clickable { onImageClick(1) }
                ) {
                    AsyncImage(
                        model = ImageRequest.Builder(LocalContext.current)
                            .data(images[1])
                            .memoryCachePolicy(CachePolicy.ENABLED)
                            .diskCachePolicy(CachePolicy.ENABLED)
                            .crossfade(true)
                            .size(100) // 设置缩略图尺寸
                            .build(),
                        contentDescription = "Journal Image 2",
                        contentScale = ContentScale.Crop,
                        modifier = Modifier.fillMaxSize(),
                        clipToBounds = true
                    )
                }

                Box(
                    modifier = Modifier
                        .weight(0.5f)
                        .fillMaxWidth()
                        .clip(RoundedCornerShape(12.dp))
                        .clickable { onImageClick(2) }
                ) {
                    AsyncImage(
                        model = ImageRequest.Builder(LocalContext.current)
                            .data(images[2])
                            .memoryCachePolicy(CachePolicy.ENABLED)
                            .diskCachePolicy(CachePolicy.ENABLED)
                            .crossfade(true)
                            .size(100) // 设置缩略图尺寸
                            .build(),
                        contentDescription = "Journal Image 3",
                        contentScale = ContentScale.Crop,
                        modifier = Modifier.fillMaxSize(),
                        clipToBounds = true
                    )
                }
            }
        }
    }

    @Composable
    fun MultipleImages(images: MutableList<Bitmap>, onImageClick: (Int) -> Unit) {
        Row(modifier = Modifier.fillMaxSize()) {
            Box(
                modifier = Modifier
                    .weight(0.5f)
                    .fillMaxHeight()
                    .padding(end = 4.dp)
                    .clip(RoundedCornerShape(12.dp))
                    .clickable { onImageClick(0) }
            ) {
                AsyncImage(
                    model = ImageRequest.Builder(LocalContext.current)
                        .data(images[0])
                        .memoryCachePolicy(CachePolicy.ENABLED)
                        .diskCachePolicy(CachePolicy.ENABLED)
                        .crossfade(true)
                        .size(150) // 设置缩略图尺寸
                        .build(),
                    contentDescription = "Journal Image 1",
                    contentScale = ContentScale.Crop,
                    modifier = Modifier.fillMaxSize(),
                    clipToBounds = true
                )
            }

            Column(
                modifier = Modifier
                    .weight(0.5f)
                    .fillMaxHeight(),
                verticalArrangement = Arrangement.spacedBy(4.dp)
            ) {
                val maxRightImages = minOf(3, images.size - 1)
                for (i in 1..maxRightImages) {
                    Box(
                        modifier = Modifier
                            .weight(1f)
                            .fillMaxWidth()
                            .clip(RoundedCornerShape(12.dp))
                            .clickable { onImageClick(i) }
                    ) {
                        AsyncImage(
                            model = ImageRequest.Builder(LocalContext.current)
                                .data(images[i])
                                .memoryCachePolicy(CachePolicy.ENABLED)
                                .diskCachePolicy(CachePolicy.ENABLED)
                                .crossfade(true)
                                .size(100) // 设置缩略图尺寸
                                .build(),
                            contentDescription = "Journal Image ${i + 1}",
                            contentScale = ContentScale.Crop,
                            modifier = Modifier.fillMaxSize(),
                            clipToBounds = true
                        )

                        if (i == maxRightImages && images.size > maxRightImages + 1) {
                            Box(
                                modifier = Modifier
                                    .fillMaxSize()
                                    .background(Color(0x80000000)),
                                contentAlignment = Alignment.Center
                            ) {
                                Text(
                                    text = "+${images.size - maxRightImages - 1}",
                                    style = MaterialTheme.typography.titleMedium,
                                    color = Color.White
                                )
                            }
                        }
                    }
                }
            }
        }
    }

    @Composable
    fun ImageSection(
        images: MutableList<Bitmap>?,
        onImageClick: (Int) -> Unit,
        modifier: Modifier
    ) {
        if (!images.isNullOrEmpty()) {
            Box(
                modifier = Modifier
                    .fillMaxWidth()
                    .height(200.dp)
                    .clip(RoundedCornerShape(12.dp))
            ) {
                when (images.size) {
                    1 -> SingleImage(images[0], onImageClick)
                    2 -> TwoImages(images, onImageClick)
                    3 -> ThreeImages(images, onImageClick)
                    else -> MultipleImages(images, onImageClick)
                }
            }
        }
    }
相关推荐
00后程序员张34 分钟前
iOS 抓不到包怎么办?从 HTTPS 解密、QUIC 排查到 TCP 数据流分析的完整解决方案
android·tcp/ip·ios·小程序·https·uni-app·iphone
李斯维2 小时前
布局性能优化利器:ViewStub 极简指南
android·性能优化
循环不息优化不止3 小时前
Ktor Pipeline 机制深度解析
android
q***56383 小时前
Springboot3学习(5、Druid使用及配置)
android·学习
q***64973 小时前
SpringSecurity踢出指定用户
android·前端·后端
q***76663 小时前
SpringSecurity 实现token 认证
android·前端·后端
Chejdj4 小时前
ViewModel#onCleared的实现原理
android·源码阅读
CheungChunChiu4 小时前
Android 系统中的 NTP 服务器配置与选择逻辑详解
android·运维·服务器
q***49864 小时前
MySQL数据的增删改查(一)
android·javascript·mysql
aqi004 小时前
FFmpeg开发笔记(九十一)基于Kotlin的Android直播开源框架RootEncoder
android·ffmpeg·kotlin·音视频·直播·流媒体