gpt4 book ai didi

android - Jetpack 撰写 : react to Slider changed value

转载 作者:行者123 更新时间:2023-12-04 03:39:02 24 4
gpt4 key购买 nike

我想显示一个 slider ,它可以由用户使用拖放更新,也可以从服务器实时更新。
当用户完成拖动手势时,我想将最终值发送到服务器。
我最初的尝试是:

@Composable
fun LightView(
channel: UiChannel,
onDimmerChanged: (Float) -> Unit
) {
val sliderValue = channel....
Slider(value = sliderValue, onValueChange = onDimmerChanged)
}
onDimmerChanged方法来自我的 ViewModel,它会更新服务器值。
但是效果很好 onValueChange每次移动都会调用它,这会用不需要的请求轰炸服务器。
我试图创建一个自定义 slider :
@Composable
fun LightView(
channel: UiChannel,
onDimmerChanged: (Float) -> Unit
) {
val sliderValue = channel....
Slider(initialValue = sliderValue, valueSetter = onDimmerChanged)
}

@Composable
fun Slider(initialValue: Float, valueSetter: (Float) -> Unit) {
var value by remember { mutableStateOf(initialValue) }
Slider(
value = value,
onValueChange = { value = it },
onValueChangeFinished = { valueSetter(value) }
)
}
它在应用程序端运行良好,并且该值仅在用户停止拖动时发送一次。
但是,当有来自服务器的更新时,它无法更新 View 。我猜这与 remember 有关.所以我尝试不使用 remember :
@Composable
fun Slider(initialValue: Float, valueSetter: (Float) -> Unit) {
var value by mutableStateOf(initialValue)
Slider(
value = value,
onValueChange = { value = it },
onValueChangeFinished = { valueSetter(value) }
)
}
这一次,当服务器更新值时 View 正确更新,但当用户拖动 slider 时不再移动。
我确定我在状态提升等方面遗漏了一些东西,但我不知道是什么。
所以我的最后一个问题 : 如何创建一个可以由 ViewModel 或用户更新的 Slider,并且只有在用户完成拖动时才通知 ViewModel 一个新值?
编辑:
我还尝试了@CommonsWare 的建议:
@Composable
fun LightView(
channel: UiChannel,
onDimmerChanged: (Float) -> Unit
) {
val sliderValue = channel....
val sliderState = mutableStateOf(sliderValue)
Slider(state = sliderState, valueSet = { onDimmerChanged(sliderState.value) })
}

@Composable
fun Slider(state: MutableState<Float>, valueSet: () -> Unit) {
Slider(
value = state.value,
onValueChange = { state.value = it },
onValueChangeFinished = valueSet
)
}
它也不起作用。使用拖放时, sliderState已正确更新,并且 onDimmerChanged()用正确的值调用。但是由于某种原因,当点击滑动(而不是滑动)时, valueSet被调用并且 sliderState.value不包含正确的值。我不明白这个值是从哪里来的。

最佳答案

这里发生了一些事情,所以让我们试着分解一下。onDimmerChanged 的初始尝试要求每一个值(value)变化看起来都很棒!
看第二次尝试,创建自定义Slider组件工作,但有一些问题。

@Composable
fun LightView(
channel: UiChannel,
onDimmerChanged: (Float) -> Unit
) {
val sliderValue = channel....
Slider(initialValue = sliderValue, valueSetter = onDimmerChanged)
}

@Composable
fun Slider(initialValue: Float, valueSetter: (Float) -> Unit) {
var value by remember { mutableStateOf(initialValue) }
Slider(
value = value,
onValueChange = { value = it },
onValueChangeFinished = { valueSetter(value) }
)
}
让我们谈谈 Slider 中发生的事情可在这里组合:
  • 我们记得 initialValue 的状态
  • channel值已更新,LightView被重组,Slider 也是如此
  • 由于我们记住了状态,所以还是设置为之前的initialValue

  • 你对 remember 的想法是对的成为这里的罪魁祸首。记住一个值时,除非我们告诉 Compose,否则它不会在重新组合时更新。但是如果没有内存(如您的第三次尝试中所见),将使用 var value by mutableStateOf(initialValue) 为每个重组( initialValue )创建一个状态模型.因为每次 value都会触发重组更改,我们将始终通过 initialValue而不是更新到 Slider 的值,导致它永远不会通过此 Composable 中的更改进行更新。
    相反,我们想通过 initialValue作为 remember 的 key ,告诉 Compose 在键更改时重新计算值。
    @Composable
    fun Slider(initialValue: Float, valueSetter: (Float) -> Unit) {
    var value by remember { mutableStateOf(initialValue) }
    Slider(
    value = value,
    onValueChange = { value = it },
    onValueChangeFinished = { valueSetter(value) }
    )
    }
    你也可以只拉 Slider进入您的 LightView :
    @Composable
    fun LightView(
    channel: UiChannel,
    onDimmerChanged: (Float) -> Unit
    ) {
    var value by remember(channel.sliderValue) { mutableStateOf(channel.sliderValue) }
    Slider(
    value = value,
    onValueChange = { value = it },
    onValueChangeFinished = { onDimmerChanged(value) }
    )
    }

    最后,关于@commonsware 建议的尝试。
    @Composable
    fun LightView(
    channel: UiChannel,
    onDimmerChanged: (Float) -> Unit
    ) {
    val sliderValue = channel....
    val sliderState = mutableStateOf(sliderValue)
    Slider(state = sliderState, valueSet = { onDimmerChanged(sliderState.value) })
    }

    @Composable
    fun Slider(state: MutableState<Float>, valueSet: () -> Unit) {
    Slider(
    value = state.value,
    onValueChange = { state.value = it },
    onValueChangeFinished = valueSet
    )
    }
    这是做同样事情的另一种方式,但绕过 MutableState s 是一种反模式,应尽可能避免。这就是状态提升有帮助的地方(您在早期尝试中尝试做的事情:))

    最后,关于 SlideronValueChangeFinished使用错误的值。

    And it does not work either. When using drag and drop, sliderState is correctly updated, and onDimmerChanged() is called with the correct value. But for some reason, when tapping of the sliding (rather than sliding), valueSet is called and sliderState.value does not contain the correct value. I don't understand where this value comes from.


    这是 Slider 中的错误。零件。您可以通过查看此代码的输出来检查这一点:
    @Composable
    fun Slider(initialValue: Float, valueSetter: (Float) -> Unit) {
    var value by remember { mutableStateOf(initialValue) }
    val key = Random.nextInt()
    Slider(
    value = value,
    onValueChange = { value = it },
    onValueChangeFinished = {
    valueSetter(value)
    println("Callback invoked. Current key: $key")
    }
    )
    }
    由于 key应该随着每次重组而改变,你可以看到 onValueChangeFinished回调包含对旧组合的引用(希望我说对了)。所以你没有发疯,这不是你的错:)
    希望这有助于澄清一些事情!

    关于android - Jetpack 撰写 : react to Slider changed value,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66386039/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com