【发布时间】:2021-12-11 02:56:00
【问题描述】:
我正在尝试使用 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() 不会观察到列表中元素的变化(成分名称/图标/库存变化)
我想向你们学习:
- 您将如何解决这个问题?
- 如果列表中的任何元素更改了其状态,我该怎么做才能实现重组?
【问题讨论】:
-
不确定如何将其组合在一起。我的成分清单现在应该采用:
storageItems: State<List<StorageItem>>吗?我现在是否在我的成分列表中使用items(storageItems.value)?试过了,也不管用,但可能我没有完全按照你的意思做。 -
我刚刚在这里回答了一个类似的问题:stackoverflow.com/a/69718724/753632
-
我查看了您的其他帖子。非常感谢您的解决方案。不过,使用随机值来更新 LiveData 对我来说并不是特别干净。现在,我想我会坚持使用 mutableStateList 直到找到完美的解决方案:D 目前的肮脏解决方法:
storageItems.add(StorageItem(Ingredient("", 0), 0))和storageItems.removeLast()
标签: android kotlin android-jetpack-compose android-viewmodel lazycolumn