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

Jetpack Compose修改List值后UI不更新,如何解决?

问题:Jetpack Compose中LazyVerticalGrid无法随State更新UI

我在Jetpack Compose项目中制作了一个包含3x3 LazyVerticalGrid的小应用,想要修改网格元素颜色但始终无法实现。点击SHUFFLE按钮时,日志显示List内的颜色标识值已改变,且已使用val cols = remember { mutableStateOf(RRCols) },但UI仍未更新。

相关代码

MainActivity.kt

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            RubiksRaceTheme {
                Surface(
                    modifier = Modifier.fillMaxSize(),
                    color = MaterialTheme.colors.background
                ) {
                    Column(
                        horizontalAlignment = Alignment.CenterHorizontally,
                        verticalArrangement = Arrangement.Center,
                        modifier = Modifier
                            .fillMaxSize()
                            .padding(top = 30.dp)
                    ) {
                        Image(painter = painterResource(id = R.drawable.rrlogo),
                            contentDescription = "Logo",
                            modifier = Modifier
                                .fillMaxWidth()
                                .padding(60.dp)
                                .scale(2f)
                        )
                        val cols = remember { mutableStateOf(RRCols) }
                        RRGrid(cols)
                        Button(onClick = { shuffle(cols) },
                            colors = ButtonDefaults.buttonColors(
                                contentColor = Color(0xFFFFFFFF),
                                backgroundColor = RRBlue
                            ),
                            modifier = Modifier
                                .fillMaxWidth()
                                .padding(horizontal = 8.dp, vertical = 50.dp)
                                .background(RRInv)
                                .size(100.dp)
                        ) {
                            Text(text = "SHUFFLE",
                                fontSize = 36.sp
                                )
                        }
                    }
                }
            }
        }
    }
}

@Composable
fun RRGrid (rrCols: MutableState<MutableList<String>>) {
    Box(contentAlignment = Alignment.Center,
        modifier = Modifier
            .fillMaxWidth()
    ) {
        LazyVerticalGrid(columns = GridCells.Fixed(3),
            contentPadding = PaddingValues(12.dp)
        ) {
            items(rrCols.value) {
                val col = RRColMap[it] ?: RRWhite
                Card(modifier = Modifier
                    .padding(4.dp)
                    .background(col)
                    .size(110.dp)
                ) {
                    Box(modifier = Modifier
                        .background(col))
                }
            }
        }
    }
}

fun shuffle(rrCols: MutableState<MutableList<String>>) {
    var check = mutableListOf<Int>(0,0,0,0,0,0)
    for (i in 0..8) {
        var num = Random.nextInt(0,6)
        while (check[num] >= 4) {
            num = Random.nextInt(0,6)
        }
        check[num] += 1
        rrCols.value[i] = RRNumCol[num] ?: "w"
    }
    Log.v("SET", RRCols.toString())
}

data.kt

var RRCols = mutableListOf("w", "w", "w", "w", "w", "w", "w", "w", "w")

val RRColMap = mapOf(
    "w" to RRWhite,
    "r" to RRRed,
    "b" to RRBlue,
    "g" to RRGreen,
    "o" to RROrange,
    "y" to RRYellow
)

val RRNumCol = mapOf(
    0 to "w",
    1 to "r",
    2 to "b",
    3 to "g",
    4 to "o",
    5 to "y"
)

解决方案

核心问题:Jetpack Compose的MutableState仅监听引用变化,修改MutableList内部元素不会改变集合引用,因此无法触发UI重组。需调整为每次更新时生成新的集合实例,触发State的引用变化。

修改步骤:

  1. 替换可变集合为不可变集合,避免直接修改原集合内部元素
  2. 每次shuffle生成新List,并赋值给State以触发重组
  3. 调整参数类型,符合Compose单向数据流原则

修改后的代码:

调整data.kt中的RRCols为不可变List

val RRCols = listOf("w", "w", "w", "w", "w", "w", "w", "w", "w")

修改MainActivity中的remember初始化

val cols = remember { mutableStateOf(RRCols) }

更新shuffle函数

fun shuffle(rrCols: MutableState<List<String>>) {
    val check = mutableListOf(0, 0, 0, 0, 0, 0)
    val newCols = mutableListOf<String>()
    for (i in 0..8) {
        var num = Random.nextInt(0, 6)
        while (check[num] >= 4) {
            num = Random.nextInt(0, 6)
        }
        check[num] += 1
        newCols.add(RRNumCol[num] ?: "w")
    }
    rrCols.value = newCols
    Log.v("SET", rrCols.value.toString())
}

修改RRGrid的参数类型

@Composable
fun RRGrid(rrCols: State<List<String>>) {
    // 内部实现保持不变
}

原理说明

  • 使用不可变List后,每次shuffle都会生成新的集合实例,赋值给State时会改变引用,触发Compose的重组机制,更新UI
  • 采用State<List<String>>替代MutableState<MutableList<String>>,符合Compose单向数据流设计,减少意外的可变副作用

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 22:32:57