我在viewmodel中存储了一个可变状态:
val state: MutableState<Int?> = mutableStateOf(null)
在我的compose UI中,我有一个LaunchedEffect监听状态变化:
LaunchedEffect(state.value) {
while(state.value != null && state.value != 0) {
...do stuff
}
}
当我用不同的valye更新状态值时,它会触发LaunchedEffect.
我试图实现的是用repeated状态值重新启动效果.
但这并不引起效果.
state.value = null
state.value = 30
而这将触发效果.
state.value = null
delay(100L)
state.value = 30
为什么我必须在这里延迟LaunchedEffect才能检测到变化?
编辑:
谢谢利维坦和查克的回答.现在更清楚了.
至于为什么我需要LaunchedEffect,我有一个可滚动的列表,每当pendingScrollState(来自业务逻辑)发生变化时,我需要以编程方式滚动:
LaunchedEffect(pendingScrollPosition.value) {
while(pendingScrollPosition.value != null && pendingScrollPosition.value != 0) {
when(pendingScrollPosition.value) {
currentPosition.value -> {
pendingScrollPosition.value // pending scroll finishes
}
else -> {
lazyListState.animateScrollBy( // animate scroll
value = calculatePendingScrollAmount(pendingScrollPosition.value)
)
}
}
}
}
有时动画滚动被用户手势取消,我需要恢复滚动.
因此,我试图重新启动效果,
val pendingScrollToResume = pendingScrollPosition.value
pendingScrollPosition.value = null
//delay(100L)
pendingScrollPosition.value = pendingScrollToResume
它不会在没有延迟的情况下重新启动.
现在我对快照系统有了更好的了解,我知道我需要一个更可靠的解决方案.
我可以通过在LaunchedEffect中添加另一个键来解决这个问题,以判断滚动何时完成:
val isScrolling = remember {
derivedStateOf {
lazyListState.isScrollInProgress
}
}
LaunchedEffect(key1 = pendingScrollPosition.value, key2 = isScrolling.value ) {
while(!isScrolling.value && pendingScrollPosition.value != null && pendingScrollPosition.value != 0) {
when(pendingScrollPosition.value) {
currentPosition.value -> {
pendingScrollPosition.value = null // pending scroll finishes
}
else -> {
lazyListState.animateScrollBy( // animate scroll
value = calculatePendingScrollAmount(pendingScrollPosition.value)
)
}
}
}
}