dimsuz
03/16/2022, 1:45 PMState
?
class State(
val value by mutableStateOf(false)
)
fun Component(state: State, reportValueChange: (Boolean) -> Unit)) {
val v = state.value
// how to call reportValueChange(v) here
// **only** when "v" changes?
}
I have tried snapshotFlow { state.value }.collect(::reportValueChange)
but it emits nothing on value changesAdam Powell
03/16/2022, 1:58 PMComponent
the thing responsible for telling the caller when state
changes, when the caller is the one providing state
to Component
?snapshotFlow
?dimsuz
03/16/2022, 2:10 PMSwipeableState
has isAnimating: Boolean
and that's how I plan to detect that swipe has finished: when isAnimating
changes from true to false.
There's a confirmStateChange
labmbda, but it's invoked too soon, prior to swipe start.snapshotFlow { swipeableState }.collect { log(it.isAnimating) }
// and
snapshotFlow { swipeableState.isAnimating }.collect { log(it) }
but the both emit the single value onlyZach Klippenstein (he/him) [MOD]
03/16/2022, 2:45 PMdimsuz
03/16/2022, 2:47 PMval swipeableState = rememberSwipeableState(initialValue = findInitialAnchor())
Timber.e("is animating ${swipeableState.isAnimationRunning}")
val flow = snapshotFlow { swipeableState.isAnimationRunning }
LaunchedEffect(Unit) {
flow.collect {
Timber.e("animated changed to ${it}, state now is ${swipeableState.currentValue}")
}
}
It's something like this.Adam Powell
03/16/2022, 2:48 PM@Test
fun snapshotFlowTest(): Unit = runBlocking {
class StateClass {
var value by mutableStateOf(false)
}
suspend fun <T> Channel<T>.receiveWithTimeout(): T = withTimeout(1000) { receive() }
val instance = StateClass()
val ch = Channel<Boolean>(Channel.BUFFERED)
val job = launch(start = CoroutineStart.UNDISPATCHED) {
snapshotFlow { instance.value }.collect { ch.send(it) }
}
assertFalse("initial value", ch.receiveWithTimeout())
Snapshot.withMutableSnapshot {
instance.value = true
}
assertTrue("after change 1", ch.receiveWithTimeout())
Snapshot.withMutableSnapshot {
instance.value = false
}
assertFalse("after change 2", ch.receiveWithTimeout())
job.cancel()
}
so yes, I'm also curious what's differentdimsuz
03/16/2022, 2:49 PMtrue
to false
for the first Timber call and only one false
for the secondChris Johnson
03/16/2022, 7:38 PMUnit
or `true`it will call the code inside your launchedEffect on every recomposition? I thought until you changed your key, it would keep the same LaunchedEffect?dimsuz
03/16/2022, 7:48 PMLaunchedEffect
body will be called as you've said: on each key change, not on each recomposition. If you provide Unit
or (literal) true
it will be called only once.Chris Johnson
03/16/2022, 7:49 PMZach Klippenstein (he/him) [MOD]
03/17/2022, 12:47 AMsnapshotFlow
even if I create it outside the effect, don’t remember it, and pass Unit
as the effect key.dimsuz
03/17/2022, 3:28 PMLaunchedEffect
at the time I had this problem: I was trying different things all at once. If I'll manage to catch this again, will try a minimal example and post here.
Thanks for looking into this, after you hints everything works fine for me!