Jetpack Compose中LazyVerticalGrid旧设备滚动卡顿问题求助
问题描述
我在非Jetpack Compose版本的应用里实现的ScrollView,在旧设备上运行流畅无卡顿。但用Jetpack Compose复刻这个滚动布局后,在运行Android 10、11的旧设备上滚动严重卡顿、画面不流畅,硬件较好的Android 13设备则运行正常。我的Compose滚动布局是一个包含50个元素的LazyVerticalGrid,每个元素是带图片和文本的Box,支持点击切换选中状态,相关代码如下:
Bar(Box = List(50) { (it + 1).toString() }) @Composable fun Bar( Box: List<String> ) { val selectedChipIndices = remember { mutableStateListOf<Boolean>() } val boxSelect: ArrayList<Int> = ArrayList() repeat(Box.size) { selectedChipIndices.add(false) } LazyVerticalGrid( columns = GridCells.Fixed(4), userScrollEnabled = true, modifier = Modifier .height(300.dp) .fillMaxWidth() ) { itemsIndexed(Box) { index, id -> Box( contentAlignment = Alignment.Center, modifier = Modifier .size(width = 100.dp, height = 70.dp) .padding(start = 10.dp, end = 5.dp, top = 10.dp, bottom = 5.dp) .clickable { selectedChipIndices[index] = !selectedChipIndices[index] if(selectedChipIndices[index]){ boxSelect.add(index) } else { boxSelect.remove(index) } } .clip(RoundedCornerShape(10.dp)) .background( if (selectedChipIndices[index]) selectblue else grey ) .padding(start = 5.dp, end = 10.dp, top = 5.dp, bottom = 5.dp) ) { Image( painter = painterResource(id = R.drawable.icon), contentDescription = "icon", contentScale = ContentScale.FillHeight, modifier = Modifier .align(Alignment.CenterStart) ) // ID Text( text = id, color = Color.White, fontSize = 24.sp, fontWeight = FontWeight.Bold, modifier = Modifier .align(Alignment.CenterEnd) ) } } }
优化方案
1. 清理冗余状态管理
- 移除重复维护的
boxSelect列表,直接用selectedChipIndices即可管理选中状态,避免状态不一致和额外计算开销。需要获取选中索引时,直接遍历selectedChipIndices提取:// 示例:获取所有选中索引 val selectedIndices = selectedChipIndices.mapIndexedNotNull { index, isSelected -> index.takeIf { isSelected } } - 优化
selectedChipIndices的初始化逻辑,避免每次重组都执行repeat:val selectedChipIndices = remember(Box.size) { MutableList(Box.size) { false } }
2. 优化图片加载性能
- 替换原生
painterResource为Coil/Glide的Compose扩展库,这类库会自动处理图片缓存、内存复用和硬件加速,大幅降低旧设备上的图片渲染开销。以Coil为例:AsyncImage( model = R.drawable.icon, contentDescription = "icon", contentScale = ContentScale.FillHeight, modifier = Modifier.align(Alignment.CenterStart) ) - 确保图片资源已适配不同DPI目录,避免运行时动态缩放消耗性能。
3. 减少不必要的重组
- 将网格项提取为独立的Composable函数,确保单个项状态变化时,仅触发该项重组,而非整个LazyGrid:
在LazyGrid中调用:@Composable fun GridItem( id: String, isSelected: Boolean, onToggle: () -> Unit ) { Box( contentAlignment = Alignment.Center, modifier = Modifier .size(100.dp, 70.dp) .padding(10.dp, 10.dp, 5.dp, 5.dp) .clickable(onClick = onToggle) .clip(RoundedCornerShape(10.dp)) .background(if (isSelected) selectblue else grey) .padding(5.dp, 5.dp, 10.dp, 5.dp) ) { // 图片和文本代码保持不变 } }itemsIndexed(Box) { index, id -> GridItem( id = id, isSelected = selectedChipIndices[index], onToggle = { selectedChipIndices[index] = !selectedChipIndices[index] } ) }
4. 适配旧Android版本的Compose优化
- 升级到最新稳定版Jetpack Compose,官方持续修复旧设备的性能问题,比如使用
compose-bom:2024.06.00及对应依赖版本。 - 发布版本中关闭Compose调试特性,在
build.gradle中添加:buildTypes { release { composeCompiler { enableDebugInspectorInfo = false } } }
内容的提问来源于stack exchange,提问作者mohammed_sajid
相关产品推荐
相关产品推荐

