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

Jetpack Compose LazyColumn列表展开项滚动后状态保留问题咨询

问题1解答

LazyColumn 本身是基于项复用的懒加载机制实现的,当列表项滚出可视区域后,对应的Greeting组件会直接从组合树中被销毁回收。你在Greeting中用remember存储的expanded状态是和组件本身的生命周期绑定的,组件销毁时状态也会同步被清除。等你滚回第一项时,Greeting会重新执行组合逻辑,remember会重新初始化expanded为默认值false,所以展开状态就恢复成初始的未展开状态了。

问题2解答

有两种常用的实现方案:

  • 方案1:状态提升,把所有列表项的展开状态提到LazyColumn的上层维护,比如在父组件中用remember存储一个Map<String, Boolean>或者Boolean类型的列表,对应每个项的展开状态,点击按钮时修改上层的状态值,Greeting组件的expanded直接从上层状态读取即可。上层组件不会因为列表滚动销毁,所以状态不会丢失。
  • 方案2:将Greeting中存储expanded的remember替换为rememberSaveable,也就是你给出的Code C的写法,即可直接实现状态保留。

问题3解答

普通Column加垂直滚动的逻辑和LazyColumn完全不同:Column会一次性把所有子项全部加入组合树,就算子项滚出可视区域也不会被销毁,只是暂时不在屏幕上渲染而已。所以Greeting组件的生命周期全程存在,用remember存储的expanded状态自然也不会被清除,滚回来的时候状态就还保留着。

注意:这种实现只适合少量列表项的场景,如果项的数量很大(比如上百上千个),一次性组合所有子项会带来非常大的性能开销,甚至出现卡顿。

问题4解答

你对rememberSaveable的认知有偏差,它的能力并不局限于配置变更场景。rememberSaveable存储状态时,会根据自身在组合树中的位置、传入的参数(这里你Greeting的name参数是唯一的,会作为状态存储的Key的一部分),将状态保存在全局的SavedStateRegistry中。
当列表项滚出屏幕Greeting被销毁时,对应Key的状态并不会被清除,等该项重新滚回可视区域、Greeting重新组合时,rememberSaveable会先去SavedStateRegistry中查找对应Key的历史状态,找到就直接复用之前的值,不会用你传入的默认值false,所以展开状态可以正常保留。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.27 01:54:05