Android Jetpack Compose LazyColumn多选重组问题求解
Android Jetpack Compose 多选功能的重组优化方案探讨
我在Android Jetpack Compose中实现多选功能时碰到了重组问题,目前已有可行方案,但对类的@Stable注解使用存在困惑,希望能获取其他实现思路。
前提条件
- 使用外部Java库中的模型类作为LazyColumn的列表项;
- LazyColumn需实现多选功能,并通过
rememberSaveable保存选中项状态。
现有实现
为实现多选,我编写了Selector类用于获取可存入Bundle的键:
class Selector<I, K> ( private val selectable: SnapshotStateList<I>, private val keyProvider: (I) -> (K) )
我将选中状态存储在映射中,关联键与选中状态:
private val _selectedStates = ArrayMap<K, WeakReference<MutableState<Boolean>>>() val selectedState: (I) -> State<Boolean> get() = state@{ item -> val key = keyProvider(item) val currentState = _selectedStates[key]?.get() return@state if (currentState != null) { currentState } else { val state = mutableStateOf(_selection.containsKey(key)) _selectedStates[key] = WeakReference(state) state } }
在LazyColumn的items块中读取状态并修改项背景:
LazyColumn( modifier = Modifier.fillMaxSize(), contentPadding = contentPadding, state = listState ) { items( items = items, key = { item -> item.hashCode() } ) { item -> val selectedState = selector.selectedState(item) val isSelected = { selectedState.value } /* 读取isSelected()的相关代码 */ } }
遇到的重组问题
当contentPadding变化时(比如滚动Scaffold的TopAppBar导致contentPadding改变),由于_selectedStates并非稳定属性,LazyColumn的所有项都会触发不必要的重组。
已尝试的方案
- 可行但存疑的方案:给
Selector类添加@Stable注解,可避免不必要的重组,但我觉得这种方式略显取巧; - 改用SnapshotStateMap:将映射改为
SnapshotStateMap(mutableStateMapOf<>())后,首次加载列表项时会触发不必要的重组——加载选中状态后存入映射,映射变化会导致LazyColumn的items块重新加载,且remember { selector.selectedState }无效果; - 不存储选中状态:仅提供
isSelected函数,此时任何选中状态变化都会导致所有项重组:
val isSelected: (I) -> Boolean = { item -> _selection.contains(keyProvider(item)) }
请问是否存在更稳定的方案,用于保存每个列表项的独立选中状态?
内容的提问来源于stack exchange,提问作者h8leet
相关产品推荐
相关产品推荐

