Jetpack Compose 中的状态提升

问题描述 投票:0回答:3

这篇文章已被编辑,以便为我的问题提供更多背景信息。我可以用我目前的知识和我能更好理解的解决方案开发的“最终”版本是这样的。如果您能分析一下并给我“确定”,我将不胜感激。我知道可能有一些更好的解决方案,但这是我的;)

            var myTextQuantityState by remember { mutableStateOf(1) }

            Text(myTextQuantityState)

            Button(
                Modifier.constrainAs(buttonAdd) {
                    end.linkTo(parent.end)
                    bottom.linkTo(buttonOrder.top)
                    top.linkTo(imageIceCream.bottom)
                },
                myTextQuantityState
            )
            { myTextQuantityState = it }
        }
    }
}

@Composable
fun Text(text: Int) {
    Text(
        text = text.toString(),
    )
}

@Composable
fun Button(
    modifier: Modifier,
    currentTextQuantityState: Int,
    increaseIceCreamQuantity: (Int) -> Unit
) {
    Button(
        onClick = {
            increaseIceCreamQuantity(currentTextQuantityState + 1)
        },
        modifier = modifier
    ) {
        
    }
}
android kotlin state hoisting
3个回答
0
投票

正如您所提到的,第二个实现目前尚未提升,因为您可以直接访问有状态值。就你能做什么而言,你 can (因为它会起作用)直接传递

MutableState<T>
,其中你同时拥有 getter 和 setter。这实际上是第一个选项通过使用委托所做的事情:

https://developer.android.com/jetpack/compose/state#state-in-composables

val (value, setValue) = remember { mutableStateOf(default) }

直接传入值 + setter lambda 与组合无关,因为如何获取值以及在 lambda 中提供的内容可以是您想要的任何内容。


如果您的目标是在多个可组合项中使用数据,并且可以选择修改数据,并且您希望避免向每个可组合项传递 getter 和 setter,那么您可以查看

CompositionLocal
:

https://developer.android.com/jetpack/compose/compositionlocal#deciding

它允许您在树层次结构中获取值,但代价是更难推理您所拥有的数据。预计一些家长会提供

CompositionLocal


0
投票

我使用 Android 已经两个月了,所以我无法告诉你“最好”的方法。但我会这样做。

var myTextQuantityState by remember { mutableStateOf(1) }

Text( text = myTextQuantityState.toString() )

Button( onClick = { myTextQuantityState += 1 } ) {}

我这样做的原因是因为我更喜欢让 lambda 能够直接访问数量,而不必像使用

increaseIceCreamQuantity
函数那样将其作为变量传递

如果状态和按钮位于不同的可组合项中,它将如何工作

@Composable
fun screen1() {
   var myTextQuantityState by remember { mutableStateOf(1) }

   Text( text = myTextQuantityState.toString() )
   screen2(increment = { myTextQuantityState += 1 })
}

@Composable
fun screen2(
   increment: () -> Unit
) {  
   Button( onClick = { increment() } ) {}
}

基于您当前的代码。解决方案还是和我上面的功能类似。您在 Button 可组合项中作为参数的

currentTextQuantityState
值实际上是对原始值的引用,因此您仍然可以传递不需要输入的 lambda。这是对您的代码的编辑,以澄清我的意思。我已将
...
跳过我未更改的代码

           ...
            Button(
                Modifier..., 
// A CHANGE HERE. NO NEED TO PASS IN myTextQuantityState. It can be modified from here by the button. The button gets the lambda and the lambda has access to myTextQuantityState. The button in your scenario does not need direct access to myTextQuantityState
                { myTextQuantityState += 1 }, // HERE IS A CHANGE
            )
            ...
}

...

@Composable
fun Button(
    modifier: Modifier, 
    increaseIceCreamQuantity: () -> Unit // HERE IS A CHANGE
) {
    Button(
        onClick = {
            increaseIceCreamQuantity() // HERE IS A CHANGE
        },
        modifier = modifier
    ) {
        
    }
}

0
投票

我最近了解了喷气背包组合中的状态提升。所以我想给大家总结一下我的学习经历。希望对你有帮助。

假设我们有一个切换按钮,并根据该按钮显示不同的过滤器。现在我们需要一个变量,其属性将控制切换行为并反映屏幕上的更改。我们可以使用状态变量来达到此目的。我们可以创建一个有状态变量并将其传递给小部件树中需要它的所有节点。现在有两种情况:

  1. 传递有状态变量本身:我们可以将有状态变量及其状态传递给树中需要它的所有节点。当节点更新其状态时,它将重组树中正在使用它的所有节点。由于我们传递的是状态本身,因此任何节点都可以修改其状态。这种方法可能会引入不必要的错误。
  2. 仅传递值:另一种方法是将状态变量的值传递给所有需要它的节点。在这里,节点仅观察有状态变量的值,并且不能修改它。当事件发生时,它会被传递到定义有状态变量的父节点,然后我们可以在那里修改它的状态。这就是所谓的
    state hoisting
    。由于我们只能在父级别更新状态,因此可以最大限度地减少错误并为我们提供更好的控制。

现在,您可以选择任何方法并使用它编写代码。如果您现在需要有关编码部分的任何帮助,请告诉我。我很乐意为您提供帮助。

© www.soinside.com 2019 - 2024. All rights reserved.