我遇到了一个非常奇怪的问题。我正在制作一种方法来处理屏幕上的点击事件,因为我想将所有指针及其 id 和位置保存在地图中,我有一个状态类,其中有此地图,并且我正在使用ViewModel 中的方法
data class RandomState(
val touchedPositions: Map<Long, Pair<Float, Float>> = emptyMap(),
)
fun updateTouchedPositions(
touchedPositions: Map < Long, Pair < Float, Float >>
) {
println("Function from viewModel: $touchedPositions")
state = state.copy(
touchedPositions = touchedPositions)
}
.pointerInput(Unit) {
awaitEachGesture {
val positions = mutableMapOf < Long, Pair < Float, Float >> ()
do {
val event = awaitPointerEvent()
val canceled = event.changes.fastAny {
it.isConsumed
}
if (event.type == PointerEventType.Press) {
event.changes.forEach { pointer - >
val id = pointer.id.value
val x = pointer.position.x
val y = pointer.position.y
positions[id] = Pair(x, y)
}
println("Se van a guardar las posiciones: $positions")
viewModel.updateTouchedPositions(positions)
println("Posiciones de dedos en onPress: ${state.touchedPositions}")
}
if (event.type == PointerEventType.Release) {
println("Posiciones de dedos en onRelease: ${state.touchedPositions}")
}
} while (!canceled)
}
}
问题是,尽管调试一切似乎都很好,但当我在 do 块的 if 内进行第二次打印时,state.touchedPositions 为空。就好像状态类以某种方式重置为默认状态,但我不知道为什么。
从您提供的代码中,尚不清楚
state
是什么以及如何在 pointerInput
中访问它,因此以下内容包括一些猜测工作。
pointerInput
是一个可组合函数,当可组合函数访问的任何状态发生更改时,通常会重新组合。然而,pointerInput
明确定义了另一种行为:与remember
或LaunchedEffect
一样,它仅在key参数更改时重新组合。由于您提供了 Unit
作为键,因此当可组合项进入组合时,pointerInput
只会执行一次。然后它捕获闭包中所需的所有变量。这就像变量当前包含的所有对象的快照。 state
就是这样一个将被捕获的对象,并且该对象将用于pointerInput
内部发生的所有事情。
当
state
变量发生变化(可能是由于重组)时,闭包仍然只包含初始对象。由于您通过使用 Unit
决定永远不应该重组 pointerInput
,因此该闭包也永远不会用当前值刷新。因此,无论您对视图模型中的状态做什么,它都永远不会达到 pointerInput
lambda。
长话短说:您需要将
Unit
替换为 state
。