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

Jetpack Compose中LazyColumn配合remember使用时子项状态丢失问题咨询

问题原因

LazyColumn子项滚出屏幕后会被回收销毁,你把remember存储的计数状态放在子项作用域内,状态会随子项销毁一起被清除,重新滑入屏幕的子项是全新创建的,自然读取不到之前的计数。

解决方案

根据你需要的状态生命周期,选对应方案即可:

方案1:仅页面存活时保留计数(无需跨配置变更/持久化)

把计数状态上提到NameList层级,用Compose可观察的mutableStateMap存储每个条目对应的计数,父级作用域不会随子项回收销毁,状态会全程保留:

@Composable
fun NameList( names: List<String>, modifier: Modifier = Modifier ){
    // 可观察Map,存储每个条目对应计数,状态生命周期和NameList一致
    val counterMap = remember { mutableStateMapOf<String, Int>() }
    LazyColumn( modifier = modifier ){
        // 给每个条目指定唯一key,避免条目顺序变更时状态错配
        items( items = names, key = { it } ) { name ->
            val currentCount = counterMap[name] ?: 0
            Row(){
                Text(text = "Hello $name")
                Counter(
                    count = currentCount,
                    updateCount = { newCount -> counterMap[name] = newCount }
                )
            }
            Divider(color = Color.Black)
        }
    }
}

如果你的条目可能存在重复name,建议给每个条目加唯一ID作为key,不要用name做key。

方案2:需跨配置变更(如屏幕旋转)/重启App保留计数

把计数状态存储到ViewModel层,ViewModel生命周期和页面绑定,不会随配置变更销毁;如果需要持久化可以在ViewModel内部结合Room、DataStore做本地存储。
示例ViewModel代码:

class NameListViewModel : ViewModel() {
    // 用MutableStateMap存储可观察的计数,也可以替换为Room等持久化方案
    private val _counterMap = MutableStateMapOf<String, Int>()
    val counterMap: Map<String, Int> = _counterMap

    fun updateCount(name: String, newCount: Int) {
        _counterMap[name] = newCount
    }
}

在Composable中获取ViewModel后读取数据、调用更新方法即可,无需把计数存到Activity的成员变量中。

之前尝试方案失效的原因
  • 状态上提至NameList时如果用普通的HashMap/List存储,Compose无法感知普通集合的数据变更,不会触发UI重组,看起来就像状态没生效,必须用mutableStateMap/mutableStateList这类可观察集合;
  • 状态定义在Counter内部时,Counter属于子项的子组件,子项回收时Counter一起销毁,内部的remember状态也会同步丢失,无法保留。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.30 14:24:01