添加新项目时,Jetpack Compose模型列表变得混乱

时间:2019-12-19 06:17:22

标签: android kotlin android-jetpack-compose

我有一个关于Jetpack的问题,即显示包含ModelList个项目的模型。添加新项目后,UI元素的顺序将变得不正确。

这是一个非常简单的CounterModel,其中包含ModelList的{​​{1}}:

ItemModel

该屏幕为每个@Model data class CounterModel( var counter: Int = 0, var name: String = "", val items: ModelList<ItemModel> = ModelList() ) @Model data class ItemModel( var name: String ) 显示两张卡行:ItemModelRowA。 创建此屏幕时,请使用以下RowB进行初始化:

CounterModel

...按预期显示,像这样:

项目1 A行

项目1 B行

项目2 A行

项目2 B行

当我单击“添加”按钮以插入新的val model = CounterModel() model.name="hi" model.items.add(ItemModel("Item 1")) model.items.add(ItemModel("Item 2")) CounterModelScreen(model) 时,我只是希望看到

项目3 A行

项目3 B行

在底部。但是相反,顺序混乱了,我看到两个rowA然后两个rowB:

项目1 A行

项目1 B行

项目2 A行

项目3 A行

项目3 B行

项目2 B行

我不太了解这是怎么可能的。 UI代码非常简单:遍历ItemModel并为每一个发出itemsRowA

RowB

使用Android Studio 4.0C6

这是完整的代码:

for (i in counterModel.items.indices) {
    RowA(counterModel, i)
    RowB(counterModel, i)
}

1 个答案:

答案 0 :(得分:1)

我已经使用 compose-1.0.0-alpha07 进行了测试,并进行了一些更改以使代码适应更改后的API。一切都可以正常工作,因此我猜测是由于旧版本的compose代码看起来正确,并且在具有上述更改的最新版本中可以工作,因此某些东西已损坏。

我还修改了您的代码以使用docs中建议的状态,并添加了一个ViewModel,它将帮助您将视图与数据管理分离:

ViewModel

if __name__ == '__main__':
    n = int(input())
    arr = map(int, input().split())
    print(sorted(list(set(arr)))[-2])

可组合视图已更新:

class CounterModelViewModel : ViewModel() {
    private val myBaseModel = CounterModel().apply {
        name = "hi"
        items.add(ItemModel("Item 1"))
        items.add(ItemModel("Item 2"))
    }

    private val _modelLiveData = MutableLiveData(myBaseModel)
    val modelLiveData: LiveData<CounterModel> = _modelLiveData

    fun addNewItem() {
        val oldCounterModel = modelLiveData.value ?: CounterModel()
        // Items is casted to a new MutableList because the new state won't be notified if the new
        // counter model content is the same one as the old one. You can also change any other
        // properties instead like the name or the counter
        val newItemsList = oldCounterModel.items.toMutableList()
        newItemsList.add(ItemModel("Item " + (newItemsList.size + 1)))
        
        // Pass a new instance of CounterModel to the LiveData
        val newCounterModel = oldCounterModel.copy(items = newItemsList)
        _modelLiveData.value = newCounterModel
    }
}

之前的代码是从另一个包含ViewModel实例的可组合函数中调用的,但是您可以将其更改为带有提到的ViewModel实例的活动或片段,这取决于您的偏好。

@Composable
fun CounterModelScreen(counterModel: CounterModel, onAddNewItem: () -> Unit) {
    ScrollableColumn {
        TopAppBar(title = {
            Text(
                text = "Counter Model"
            )
        })

        CounterHeader(counterModel)
        counterModel.items.forEachIndexed { index, item ->
            RowA(counterModel, index)
            RowB(counterModel, index)
        }
        Button(
            onClick = onAddNewItem
        ) {
            Text(text = "Add")
        }
    }
}

@Composable
fun CounterHeader(counterModel: CounterModel) {
    Text(text = counterModel.name)
}

@Composable
fun RowA(counterModel: CounterModel, index: Int) {

    Card(
        backgroundColor = Color.White,
        shape = RoundedCornerShape(4.dp),
        modifier = Modifier.padding(8.dp)
    ) {
        Column(modifier = Modifier.fillMaxWidth()) {
            Text(
                text = counterModel.items[index].name
            )
            Text(text = "Row A")
        }
    }

}

@Composable
fun RowB(counterModel: CounterModel, index: Int) {

    Card(
        backgroundColor = Color.Gray,
        shape = RoundedCornerShape(4.dp),
        modifier = Modifier.padding(8.dp)
    ) {
        Column(modifier = Modifier.fillMaxWidth()) {
            Text(
                text = counterModel.items[index].name
            )
            Text(text = "Row B")
        }
    }

}