簡體   English   中英

使用 android Jetpack compose 中的列表處理 state

[英]Handling state using list in android Jetpack compose

我正在嘗試更新一個列表,該列表保留為可組合視圖的 state,但即使列表的值已更改,可組合視圖也不會重新組合。

var list = remember {mutableStateOf(getListOfItems())}
ItemListView({ selectedItem ->
       list.value =  updateList(selectedItem, list.value)
            }, list.value)

private fun updateList(selectedItem: String,
         itemsList: List<Product>): List<Product> {
    for (item in itemsList){
        // selected item in the view is updated
        item.selected = item.name == selectedItem
    }
    return itemsList
}

知道為什么可組合組件沒有更新嗎? 我注意到當使用列表作為 state 時會發生此問題。

您需要更新MutableStatevalue (在您的示例中是一個List ),以觸發重組,而不是您設置為MutableState的任何值屬性。

@Stable
interface MutableState<T> : State<T> {
    override var value: T
    operator fun component1(): T
    operator fun component2(): (T) -> Unit
}

但是還有另一個名為mutableStateListOf()的 function 可以在您添加或刪除項目或使用新實例更新現有項目時觸發重組。

val list =remember {
    mutableStateListOf< Product>().apply {
        addAll(getListOfItems())
    }
}

jetpack compose 會查看您的 object 本身,看看它是否已更改以決定是否更新它。 您需要更新列表本身才能做到這一點:

data class A(var v: Int)

@Composable
fun Test1() {
    var list by remember { mutableStateOf(listOf(A(1), A(2), A(3))) }
    LazyColumn(modifier = Modifier.fillMaxSize()) {
        items(list) {
            Text(text = it.toString())
        }

        item {
            // it does not work
            Button(onClick = {
                list[0].v = 2
            }) { Text("Change value") }

            // it works
            Button(onClick = {
                list = list.map { it.copy(v = it.v + 1) }
            }) { Text("Change list") }
        }
    }
}

此外,您可以使用 mutableStateListOf,它會監視元素的添加和刪除。

@Composable
fun Test2() {
    val list = remember { mutableStateListOf(A(1), A(2), A(3)) }
    LazyColumn(modifier = Modifier.fillMaxSize()) {
        items(list) {
            Text(text = it.toString())
        }

        item {
            // it not work
            Button(onClick = {
                list[0].v = 2
            }) { Text("Change value") }

            // it work
            Button(onClick = {
                list.add(A(3))
            }) { Text("Change list") }
        }
    }
}

在您的情況下,您可以像這樣表示選擇:

val selectedList = remember { mutableStateListOf<String>() }
LazyColumn(modifier = Modifier.fillMaxSize()) {
    items(list) {
        val selected = selectedList.contains(it.name)
        Text(text = if (selected) "selected" else "not selected")
        Button(onClick = {
            if (!selected) selectedList.add(it.name)
        }) { Text("Select it") }
    }
}

通過獲取具有新值的列表副本來解決此問題:

private fun updateList(selectedItem: String,
     itemsList: List<Product>): List<Product> {
 val updatedList = itemsList.map { product -> 
 if(product.name == selectedItem) {
    product.copy(selected = true)
  } else {
    product.copy(selected = false)
  }
 }
 return updatedList 
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM