Thread
#compose
    zhuinden

    zhuinden

    1 year ago
    I'm trying to make SaveableStateProvider work - I have Parcelable immutable data classes as keys (so hashCode/equals) and ensure SavedStateProviders exist while the keys are added, yet I'm still losing the saved state. What am I missing?
    Layout(
                    content = {
                        allKeys.fastForEach { key ->
                            key(key) {
                                saveableStateHolder.SaveableStateProvider(key = key) {
                                    if (key == topNewKey || (isAnimating && key == initialNewKey)) {
                                        Box(
                                            modifier = when {
                                                !isAnimating || initialization -> modifier
                                                else -> when {
                                                    key == topNewKey -> newTransition.animateComposable(modifier, stateChange, fullWidth, fullHeight, animationProgress)
                                                    else -> previousTransition.animateComposable(modifier, stateChange, fullWidth, fullHeight, animationProgress)
                                                }
                                            }
                                        ) {
                                            key.RenderComposable(modifier)
                                        }
                                    }
                                }
                            }
                        }
                    },
                    measurePolicy = measurePolicy,
                )
    ^ theoretically I would think that
    SaveableStateProvider
    should store stuff in the "local saved state registry" which as I do not supply a custom one, should be the Activity
    why would it lose state as I navigate forward? 🤔
    or i should just give up on making
    rememberSaveable
    work, although that sounds not ideal
    🤔
    Andrey Kulikov

    Andrey Kulikov

    1 year ago
    @Immutable
    @Parcelize
    class SecondKey: ComposeKey() {
        @Composable
        override fun ScreenComposable(modifier: Modifier) {
            SecondScreen(modifier)
        }
    }
    is it how you define your keys?
    zhuinden

    zhuinden

    1 year ago
    yep
    so
    @Immutable
    @Parcelize
    data class DogListKey(private val noArgPlaceholder: String = "") : ComposeKey() {
        @Suppress("RemoveExplicitTypeArguments")
        override fun bindServices(serviceBinder: ServiceBinder) {
            super.bindServices(serviceBinder)
            with(serviceBinder) {
                add(DogListViewModel(lookup<DogDataSource>()))
            }
        }
    
        @Composable
        override fun ScreenComposable(modifier: Modifier) {
            val viewModel = rememberService<DogListViewModel>()
    
            val dogs = viewModel.dogList.subscribeAsState(OptionalWrapper.absent())
    
            DogListScreen(dogs.value.value)
        }
    }
    Andrey Kulikov

    Andrey Kulikov

    1 year ago
    you said the state is lost when you navigate forward? what does it mean? so you are on DogListKey screen, then you open another one while the list screen is in the backstack and then go back to the list screen?
    zhuinden

    zhuinden

    1 year ago
    yep
    the LazyList starts at the top again 🤔
    *LazyColumn i mean
    i figured adding the savedStateProvider would help, but it didn't, even though i know that LazyColumn remembers the lazy scroll state and should therefore rely on the Saver to restore it
    although now that i think about it, i should probably try this with a standard "Text" component to see if subcomposition has something to do with it 👀
    Andrey Kulikov

    Andrey Kulikov

    1 year ago
    so I tested your sample and you almost did it correct
    aside from the ordering
    here you need to first have
    if (key == topNewKey || (isAnimating && key == initialNewKey))
    and only then
    saveableStateHolder.SaveableStateProvider(key = key)
    why: because when you stop displaying the previous screen after the animation is finished SaveableStateProvider should also be disposed so the state is saved. if you have it before if the provider is still alive and knows nothing about the screen not being displayed anymore
    zhuinden

    zhuinden

    1 year ago
    oooh so it has to get detached to save, it's kinda the opposite than i thought (because for ensuring the composeHash to be the same, i had to make sure stuff is stable and alive), thanks for info i'll check it out 👍
    Andrey Kulikov

    Andrey Kulikov

    1 year ago
    rememberSaveableStateHolder() should be called outside of it so it stays active, but the separate providers on it should have the same lifecycle as the screens
    zhuinden

    zhuinden

    1 year ago
    amazing, it really does work now, thank you 🥳 🥳 🥳