Tob*_* M. 8 android kotlin android-viewmodel android-jetpack-compose lazycolumn
我正在尝试 Android 的 Jetpack Compose。
\n对于简单的用例,一切都按预期工作,
\n但我在缺少更高级案例的重组方面遇到了一些麻烦。
我的型号:
\n我正在模拟一个原料存储系统,其中
\ndata class Ingredient(val name: String, @DrawableRes val iconResource: Int? = null)\ndata class StorageItem(val ingredient: Ingredient, var stock: Int)\n我的可组合项:
\n我的StorageUi可组合项应该列出所有存储项目
\n并显示成分的图标和名称以及库存。
\n对于这篇文章,我删除了所有不相关的修饰符和格式以简化可读性。
\n(请注意,我使用没有视图模型的第二个版本重载了 StorageScreen 可组合项,
\n是为了更轻松地进行测试并促进 Android Studio 中的预览功能。)
    @Composable\n    fun StorageScreen(viewModel: StorageViewModel) {\n        StorageScreen(\n            navController = navController,\n            storageItems = viewModel.storageItems,\n            onIngredientPurchased = viewModel::purchaseIngredient\n        )\n    }\n\n    @Composable\n    fun StorageScreen(storageItems: List<StorageItem>, onIngredientPurchased: (StorageItem) -> Unit) {\n        Column {\n            TitleBar(...)\n            IngredientsList(storageItems, onIngredientPurchased)\n        }\n    }\n\n    @Composable\n    private fun IngredientsList(storageItems: List<StorageItem>, onIngredientPurchased: (StorageItem) -> Unit) {\n        LazyColumn {\n            items(storageItems) { storageItem ->\n                IngredientCard(storageItem, onIngredientPurchased)\n            }\n        }\n    }\n\n    @Composable\n    private fun IngredientCard(storageItem: StorageItem, onIngredientPurchased: (StorageItem) -> Unit) {\n        Card(\n            Modifier.clickable { onIngredientPurchased(storageItem) }\n        ) {\n            Row {\n                ImageIcon(...)\n\n                Text(storageItem.ingredient.name)\n\n                Text("${storageItem.stock}x")\n            }\n        }\n    }\n我的视图模型:
\n在我的 ViewModel 中,我
\n    class StorageViewModel : ViewModel() {\n\n        var storageItems = mutableStateListOf<StorageItem>()\n            private set\n\n        fun purchaseIngredient(storageItem: StorageItem) {\n            storageItem.stock += 1\n        }\n\n    }\n问题:更改原料库存时不会发生重组
\n我尝试更改事件处理程序以简单地从列表中删除点击的项目:
\n        fun purchaseIngredient(storageItem: StorageItem) {\n            storageItems.remove(storageItem)\n        }\n然后瞧\xc3\xa0,UI 重新组合,点击的成分消失了。
\n我学到的是:
\n我想向你们学习的是:
\n如果列表中的任何元素更改其状态,我该怎么做才能实现重组?
仅当您更改列表本身时才会发生重组。你可以这样做。
class StorageViewModel : ViewModel() {
     var storageItems by mutableStateOf(emptyList<StorageItem>())
        private set
     fun purchaseIngredient(storageItem: StorageItem) {
        storageItems = storageItems.map { item ->
            if(item == storageItem)
                item.copy(stock = item.stock + 1)
            else
                item
        }
     }
}
由于这是一个非常常见的操作,因此您可以创建一个扩展函数以使其看起来更好一些。
fun <T> List<T>.updateElement(predicate: (T) -> Boolean, transform: (T) -> T): List<T> {
    return map { if (predicate(it)) transform(it) else it }
}
fun purchaseIngredient(storageItem: StorageItem) {
    storageItems = storageItems.updateElement({it == storageItem}) {
        it.copy(stock = it.stock + 1)
    }
}
| 归档时间: | 
 | 
| 查看次数: | 8191 次 | 
| 最近记录: |