Colton Idle
08/03/2021, 9:39 PM@Composable
fun SignUpScreen(
viewModel: SignUpViewModel = hiltViewModel()
) {
val pagerState = rememberPagerState(5)
In order to have a single source of truth, should I just move val pagerState = rememberPagerState(5)
into my ViewModel?Shakil Karim
08/03/2021, 10:37 PMShakil Karim
08/03/2021, 10:39 PMAlex Vanyo
08/03/2021, 10:53 PMSavedStateHandle
with the Compose Saver
APIs:
https://gist.github.com/alexvanyo/0406250c67e02fae36dd5360e915bed2
Usage looks like
val pagerState: PagerState = savedStateHandle.saveable(
key = "pagerState",
saver = PagerState.Saver
) {
PagerState(
pageCount = 10,
offscreenLimit = 2,
)
}
which sort of mimics rememberSaveable
Colton Idle
08/03/2021, 11:06 PMShakil Karim
08/03/2021, 11:07 PMdimsuz
08/03/2021, 11:40 PMColton Idle
08/04/2021, 1:11 AMcb
08/05/2021, 9:43 AMsnapshotFlow
or hoist the state to the VM mostly depends on what is the source of truth.
Does the VM need to know about every change of the Pager? If so, hoisting makes sense.
If it just needs to know about a page change event, hoisting might be a bit over the top.
As with a lot of things in software dev, it depends 😬cb
08/05/2021, 9:46 AMSavedStateHandle
is an Android thing. If you ever want to go KMP then you need to rely on saveable (which rememberPagerState()
already does)Colton Idle
08/05/2021, 1:37 PMShakil Karim
08/05/2021, 2:36 PMAlex Vanyo
08/05/2021, 3:18 PManimateScrollToPage
should be a suspend fun
which you could call from any suspending context from your ViewModel
if your pagerState
is hoisted there.
If your ViewModel
exposes a suspend fun
, the animation could still be tied to a scope driven by a specific composable (rememberCoroutineScope()
or LaunchedEffect
), otherwise it could be a scope that outlives composition (like viewModelScope
)Colton Idle
08/05/2021, 3:26 PMval pagerState = rememberPagerState(5)
into my VM, but it didn't compile. I don't think I can put rememberPagerState into the VM that way? But again, I'm very new to this. maybe I'm missing something basic Alex.Alex Vanyo
08/05/2021, 3:38 PMrememberPagerState
is annotated with @Composable
, so you can only call that from a @Composable
function. It needs to be, since its implementation calls @Composable rememberSaveable
. AAC `ViewModel`s outlive composition, so you can’t call any @Composable
functions from them.
However, PagerState
itself is a state holder, which doesn’t have to exist within a @Composable
, and can be hoisted out of it completely.
So you could do val pagerState = PagerState(5)
in your ViewModel
instead. The downside there is that the pager state won’t be saved through process death, which rememberPagerState
does protect you against (via rememberSaveable
)
To fix that, you could either listen for changes to save to SavedStateHandle
(with snapshotFlow
) or the gist I shared earlierColton Idle
08/05/2021, 4:25 PMShakil Karim
08/05/2021, 10:19 PMjava.lang.IllegalStateException: A MonotonicFrameClock is not available in this CoroutineContext. Callers should supply an appropriate MonotonicFrameClock using withContext.
But I think it is due to animateScrollToPage
called from ViewModelScope.dimsuz
08/06/2021, 10:13 AM