当前位置: 首页 > 知识库问答 >
问题:

Jetpack合成:更新列表元素内容时,没有发生重组

鲁才艺
2023-03-14

我正在试验Android的Jetpack Compose。
对于简单的用例,一切都按预期工作,
但我在错过更高级案例的重组方面遇到了一些麻烦。
这是我在stackoverflow上的第一篇文章。我希望我能很好地描述我的问题以获得一些帮助。;)

我的模型:

我正在模拟配料的存储系统,其中

    < li >配料由名称和可选图标组成:
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")
            }
        }
    }

我的视图模型:

在我的视图模型中,我

    < li >创建可变状态列表(此处未显示初始化数据) < li >如果用户点击配料卡,则提供增加库存的事件处理程序
    class StorageViewModel : ViewModel() {

        var storageItems = mutableStateListOf<StorageItem>()
            private set

        fun purchaseIngredient(storageItem: StorageItem) {
            storageItem.stock += 1
        }

    }

问题是:当改变一种配料的库存时,没有重组发生

我尝试更改事件处理程序,以简单地从列表中删除点击的项:

        fun purchaseIngredient(storageItem: StorageItem) {
            storageItems.remove(storageItem)
        }

瞧,用户界面重新组合,被点击的成分消失了。

我学到了什么:

    < li>mutableStateListOf()观察列表的变化(添加、删除、重新排序) < li>mutableStateListOf()不会观察列表中元素的变化(配料名称/图标/库存变化)

我想向你们学习的是:

  • 你将如何着手解决这个问题
  • 如果列表中的任何元素改变其状态,我可以做些什么来实现重新编译

共有1个答案

司寇正志
2023-03-14

如果列表中的任何元素更改其状态,我可以做些什么来实现重组?

仅当您更改列表本身时,才会进行重新组合。你可以这样做。

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)
    }
}

 类似资料:
  • 我正在尝试使用RxAndroid Flowable的订阅者更新LazyColumn项目。我用于图像列表的状态变量简称为“列表” 这是我的懒惰列代码: 例如,如果我运行此测试协程,列表将更新并显示正确数量的测试图像: 但是,如果我使用对Flowable的订阅尝试相同的方法,它会更新变量值,但不会触发重新编译。这是我的代码: 我如何处理一个可组合的流动?

  • 假设我有一个由n个字符串列表组成的列表: result->包含所有输出列表(所有组合) current->是当前的组合 用上述相同示例调用此函数时的输出:

  • 我想要一个列表,它是列表元素列表的组合,例如:我的输入 输出应该是 非常感谢您的帮助。

  • 我的模式是: 我的xml将是: 案例1。 或案例2。 对于案例2,没有问题。但对于案例1,我得到了以下错误: 如何修改wsdl,使其同时接受案例1和案例2?请帮忙。

  • 我有客户对象的列表。我想迭代列表并按1递增顺序。 我尝试了每个列表,但在这里我必须创建新列表并在其中添加值。 有没有更好的方法?我尝试使用streams,但它只是映射订单

  • 通过列表综合,可以从一个已有的列表导出一个新的列表。例如,你有一个数的列表,而你想要得到一个对应的列表,使其中所有大于2的数都是原来的2倍。对于这种应用,列表综合是最理想的方法。 使用列表综合 例15.1 使用列表综合 #!/usr/bin/python # Filename: list_comprehension.py listone = [2,3,4] listtwo = [2*iforiin