Chris Johnson
03/22/2022, 10:45 PMscrollState.isScrollInProgress
changes from false to true or true to false. I don't want to use a LaunchedEffect with a key to avoid creating a new CoroutineScope everytime someone starts/stops scrolling.Filip Wiesner
03/23/2022, 5:35 AMDisposableEffect
has a key parameters and does not create a Coroutine scopeChris Johnson
03/23/2022, 6:05 AMZach Klippenstein (he/him) [MOD]
03/23/2022, 6:14 PMLaunchedEffect(scrollState.isScrollInProgress)
is not that you’re creating a coroutine for every time scroll starts/stops – that’s perfectly find (the entire animation system works that way, including scroll flings). The problem is that it requires recomposition unnecessarily.
I think this is what you’re looking for:
LaunchedEffect(scrollState, …) {
snapshotFlow { scrollState.isScrollInProgress }
.collect { isScrolling ->
…
}
}
Chris Johnson
03/23/2022, 6:17 PMscrollState.isScrollInProgress
over and over?Zach Klippenstein (he/him) [MOD]
03/23/2022, 8:27 PMisScrollInProgress
in the composable in order to pass it to LaunchedEffect
as a key, then that’s going to recompose every time that state changes.Chris Johnson
03/23/2022, 8:30 PMZach Klippenstein (he/him) [MOD]
03/23/2022, 8:43 PMChris Johnson
03/23/2022, 9:05 PMjames
03/23/2022, 10:43 PMval isScrolling by remember {
derivedStateOf { scrollState.isScrollInProgress }
}
if (isScrolling) {
LaunchedEffect(isScrolling) {
// ...
}
}
is this an okay practice? or should I be changing my code to something like the snapshotFlow example you posted above?myanmarking
04/05/2022, 11:47 AMAlbert Chang
04/05/2022, 1:58 PMderivedStateOf
here as remember { derivedStateOf { scrollState.isScrollInProgress } }
is the same as scrollState.isScrollInProgress
if scrollState
doesn’t change (which is likely the case).
@myanmarking scrollState.isScrollInProgress
comes from a snapshot state and will trigger recomposition.myanmarking
04/05/2022, 9:53 PMAlbert Chang
04/06/2022, 1:24 AMscrollState
is unlikely to change as it is normally created by rememberScrollState()
and in that case derivedStateOf
makes no point.Zach Klippenstein (he/him) [MOD]
04/14/2022, 7:02 PMderivedStateOf
simply to read the value of isScrollInProgress
, since the rate of change is the same.
Where it makes sense to use derivedStateOf
with scrolling is, for example, if you need to calculate some condition based on the scroll value. In that case, the rate of change of the scroll state is very frequent – every frame during a scroll/fling – but the rate of change of the derived state is much lower. E.g.
val isNearTop by remember(scrollState) { derivedStateOf { scrollState.value < 10 } }
snapshotFlow
vs keying a LaunchedEffect
off the changing value, the latter requires more unnecessary recomposition than the former. If the rate of change is low, as it is for isScrollInProgress
, that’s a negligible cost. But it’s also just more moving parts, and imo less elegant. When the value changes, you trigger a recomposition, that starts a new effect, which starts a new coroutine, which will get torn down when the value changes again. Vs with snapshotFlow
, you start one coroutine, it runs continuously, and the only thing that happens when the state changes is a new flow emission. I’m guessing the snapshotFlow
approach will also scale better if your logic grows in complexity.james
04/19/2022, 12:44 AM