Sev*_*nds 1 android-jetpack-compose lazycolumn
我正在为我的应用程序开发购物车功能。我希望分别添加/减少 LazyColumn 中每个列表项的数量。我只使用一个“记住”,因此如果我单击添加/减少,它们都会同时更新。如何单独控制每个项目?
@Composable
fun InventoryCartScreen(
mainViewModel: MainViewModel = hiltViewModel()
) {
val multiSelectValue = mutableStateOf(0)// This is the value I want to change
//random list
val shopList = listOf(
ShoppingList(id = 0,itemNumber = "1",itemDescription = "1",currentInventory = 0,optimalInventory = 0,minInventory = 0),
ShoppingList(id = 0,itemNumber = "2",itemDescription = "2",currentInventory = 0,optimalInventory = 0,minInventory = 0)
)
Column(...) {
LazyColumn(...) {
items(items = shopList, key = { it.id }) { item ->
InventoryCartScreenContents(
onaddClick= { multiSelectValue.value ++ }, //adds for all
onDecreaseClick = { multiSelectValue.value -- }, //decreases for all
value = multiSelectValue.value //setting the initial value for all
)
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
以下是可帮助您重现问题的可组合内容。
@Composable
fun InventoryCartScreenContents(
onAddClick: (Int) -> Unit,
onDecreaseClick: () -> Unit,
value: Int,
) {
Row(...) {
Button(
onClick = { onAddClick(itemId) }
) {
Text(text = "+")
}
Button(
onClick = onDecreaseClick
) {
Text(text = "-")
}
}
}
Run Code Online (Sandbox Code Playgroud)
Ric*_*per 12
在您的mutableStateListOf(...). 现在,从您想要读取它的可组合项(即您的.mutableStateOf(listOf(...))ViewModelLazyColumn
在您的 中ViewModel,您可以根据需要设置值,并且它们将在更新时在可组合项中更新。现在,可组合项(即您的列)可以使用列表项的索引作为惰性列项的索引。因此,您可以在视图模型中为不同的项目存储不同的数据,并且它会正常工作。
问题似乎是您在这里缺少状态提升的概念。我以为我有一些很好的帖子解释了它,但似乎这是我发布的最好的帖子。不管怎样,我建议检查这个官方参考资料,因为我基本上就是在那里找到的(可以说,有一点猎头。)
基本思想是所有内容都存储在 viewModel 中。然后,将该状态分为“setter”和“getters”,并将它们沿层次结构传递。
例如,ViewModel 可能有一个名为 的项目text,好吗?
class VM : ViewModel(){
var text by mutableStateOf("Initial Text")
private set // This ensures that it cannot be directly modified by any class other than the viewmodel
fun setText(newText: Dtring){ // Setter
text = newText
}
}
Run Code Online (Sandbox Code Playgroud)
text如果您希望在单击按钮时更新 的值,则可以通过以下方式将该按钮与 viewModel 连接起来
MainActivity{
onCreate{
setContent{
StateButton(
getter = viewModel.text, // To get the value
setter = viewModel::setText // Passing the setter directly
)
}
}
}
Run Code Online (Sandbox Code Playgroud)
在您的 Button Composable 声明中
@Composable
private fun ComposeButton(
getter: String,
setter: (String) -> Unit // (receive 'String') -> return 'Unit' or 'void'
){
Button(
onClick = { setter("Updated Text") } // Calls the setter with value "Updated Text", updating the value in the viewModel
){
Text(text = getter)
}
}
Run Code Online (Sandbox Code Playgroud)
此按钮从 viewModel 读取值“get”,即,它读取 的值text,因为它从模型传递到可组合项。然后,当我们从按钮(在 中onClick)收到单击事件时,我们调用作为可组合项参数收到的 setter,并使用新值调用它,在本例中为“更新的文本”,这将一直向上到 viewModel,并更改text其中的值。
现在,text最初通过在初始化中使用来初始化为状态持有者mutableStateOf(...),这将在其值发生更改时触发重组。现在,由于值实际上确实发生了变化(从“初始文本”到“更新文本”),因此将在读取变量值的所有可组合项上触发重组text。现在,我们的ComposeButtonComposable 确实读取了 的值text,因为我们直接将其传递给getter该 Composable 的参数,对吗?因此,所有这些都将产生一个可组合项,它将从层次结构(视图模型)中的单个点读取值,并且仅在该值更改时更新。因此,Viewmodel 充当可组合项的单一事实来源。
运行此命令时,您将得到一个可组合项,该可组合项最初显示为“初始文本”,但当您单击它时,它会更改为“更新的文本”。我们在 getter 和 setter 的帮助下将可组合项连接到主 viewModel。当可组合项接收事件时,我们调用从模型接收的 setter,这些 setter 将链继续向上至 viewModel,并更改模型内变量(状态持有者)的值。然后,可组合项已经通过“getters”读取这些变量,因此,它们重新组合以反映更新的值。这就是状态提升。所有状态都存储在 viewModel 中,并传递给可组合项。当值需要更改时,可组合项将“事件”向上传递到 viewModel(沿层次结构向上),然后在更新值时,更新后的状态将向下传递到可组合项(“状态”沿层次结构向下流动) 。
您所需要的只是使用此方法,但带有一个列表。您可以使用项目的索引来跟踪项目,并在 viewModel 中更新它们的属性,就像本示例演示的更新 的值一样a。您可以将项目的所有属性存储在单个列表中。
只需创建一个数据类,就像这样
data class Item(p1: ..., p2:..., p3 : ...){}
Run Code Online (Sandbox Code Playgroud)
然后,val list by mutableStateOf(listOf<Item>())
清除?
好的,这是针对您的用例的具体解释。
您的代码似乎太大了,但这是我得到的:
惰性列中有两个项目,每个项目都有三个按钮。你的问题是关于两个按钮,增加和减少。您希望按钮仅修改它们所属项目的属性,对吧?
好吧,再次使用状态提升,如上所述
ViewModel{
val list by mutableStateOf(listOf<Item>()) // Main (central) list
val updateItem(itemIndex: Int, item: Item){
list.set(itemIndex, item) // sets the element at 'itemIndex' to 'item'
} // You can fill the list with initial values if you like, for testing
}
Run Code Online (Sandbox Code Playgroud)
创建 Getter 和 Setter 后,您将使用它们来读取和更新整个项目,即使您必须修改它们的单个属性。我们可以使用便利的方法来copy()让我们的生活更轻松。
MainScreen(){
//Assuming here is the LazyColumn
list = viewModel.list // Get the central list here
LazyColumn(...){ // Try to minimize code like this in your questions, since it does not have to compile, just an illustration.
items(list){ item ->
// Ditch the multiSelectValue, we have the state in the model now.
Item( // A Composable, like you demonstrated, but with a simpler name for convenience
item: Item,
onItemUpdate: (Item) -> Unit // You don't need anything else
)
}
}
}
Run Code Online (Sandbox Code Playgroud)
只需创建一个数据类并将所有内容存储在其中即可。我演示的类Item(不是可组合类)是数据类。它可能有这样的值
data class Item(var quantity: Int, ...){} // We will increase/decrease this
Run Code Online (Sandbox Code Playgroud)
现在,在您的Item可组合项中,您收到“添加”事件(在onClick“添加”按钮中),只需使用设置器更新值,如下所示
onClick = {
updateItem(
item // Getter
.copy( //Convenience Method
quantity = item.quantity + 1 // Increase current Quantity
)
)
}
Run Code Online (Sandbox Code Playgroud)
只需对减少和删除 ( ) 执行相同的操作updateItem(0),您就应该很好地完成此操作...最后。如果您还有任何疑问,请尽管询问。如果没有任何效果,我可以通过视频通话提供帮助。
| 归档时间: |
|
| 查看次数: |
17717 次 |
| 最近记录: |