我正在尝试使用 Android 的 Jetpack Compose。
对于简单的用例,一切都按预期工作,但是对于更高级的用例,
我在缺少重组时遇到了一些麻烦。
这是我在 stackoverflow 上的第一篇文章。我希望我能很好地描述我的问题以获得一些帮助。;)
我的模型:
我正在模拟成分的存储系统,其中
- 成分由名称和可选图标组成:
data class Ingredient(val name: String, @DrawableRes val iconResource: Int? = null)
- 一个StorageItem由一种成分和一种库存(该成分的存储量)组成:
data class StorageItem(val ingredient: Ingredient, var stock: Int)
我的可组合物:
我的StorageUi组合应该列出所有存储项目
,并显示成分的图标和名称,以及库存。
对于这篇文章,我去掉了所有不相关的修饰符和格式以简化可读性。
(请注意,我用第二个没有视图模型
的版本重载了我的 StorageScreen 组合,以便于测试并促进 Android Studio 中的预览功能。)
@Composable
fun StorageScreen(viewModel: StorageViewModel) {
StorageScreen(
navController = navController,
storageItems = viewModel.storageItems,
onIngredientPurchased = viewModel::purchaseIngredient
)
}
@Composable
fun StorageScreen(storageItems: List<StorageItem>, onIngredientPurchased: (StorageItem) -> Unit) {
Column {
TitleBar(...)
IngredientsList(storageItems, onIngredientPurchased)
}
}
@Composable
private fun IngredientsList(storageItems: List<StorageItem>, onIngredientPurchased: (StorageItem) -> Unit) {
LazyColumn {
items(storageItems) { storageItem ->
IngredientCard(storageItem, onIngredientPurchased)
}
}
}
@Composable
private fun IngredientCard(storageItem: StorageItem, onIngredientPurchased: (StorageItem) -> Unit) {
Card(
Modifier.clickable { onIngredientPurchased(storageItem) }
) {
Row {
ImageIcon(...)
Text(storageItem.ingredient.name)
Text("${storageItem.stock}x")
}
}
}
我的视图模型:
在我的 ViewModel 中,我
- 创建一个可变状态列表(此处未显示数据的初始化)
- 如果用户点击成分卡,则提供增加库存的事件处理程序
class StorageViewModel : ViewModel() {
var storageItems = mutableStateListOf<StorageItem>()
private set
fun purchaseIngredient(storageItem: StorageItem) {
storageItem.stock += 1
}
}
问题:改变原料的库存时不会发生重组
我尝试更改事件处理程序以简单地从列表中删除被点击的项目:
fun purchaseIngredient(storageItem: StorageItem) {
storageItems.remove(storageItem)
}
瞧,UI 重新组合,轻拍的成分消失了。
我学到的是:
- mutableStateListOf() 确实观察到列表的变化(添加、删除、重新排序)
- mutableStateListOf() 不会观察到列表中元素的变化(成分名称/图标/库存变化)
我想从你们那里学到什么:
- 你将如何解决这个问题?
- 如果列表中的任何元素更改其状态,我该怎么做才能实现重组?