Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

runtime-saveable: supports tvos and watchos #3521

Closed
hoc081098 opened this issue Aug 17, 2023 · 6 comments
Closed

runtime-saveable: supports tvos and watchos #3521

hoc081098 opened this issue Aug 17, 2023 · 6 comments
Assignees
Labels
enhancement New feature or request runtime Compose runtime problem

Comments

@hoc081098
Copy link

Currently, this modules supports android, jvm, js, ios and macos.
Please support tvos and watchos.

@hoc081098 hoc081098 added enhancement New feature or request submitted labels Aug 17, 2023
@mazunin-v-jb
Copy link
Contributor

Hello, thanks for the issue!
I'll pass it on to the team.

@dima-avdeev-jb
Copy link
Contributor

dima-avdeev-jb commented Aug 18, 2023

For now, runtime-saveable have a sence only for Android. For other platform it works the same as remember. So, you can create your own expect fun myRememberSaveable(...) withactual fun myRememberSaveable(...) = remember(...) on all platforms and only one real implementation on androidMain sourceSet: actual fun myRememberSaveable() = rememberSaveable(...)

@dima-avdeev-jb dima-avdeev-jb added the runtime Compose runtime problem label Aug 18, 2023
@hoc081098
Copy link
Author

hoc081098 commented Aug 18, 2023

For now, runtime-saveable have a sence only for Android. For other platform it works the same as remember. So, you can create your own expect fun myRememberSaveable(...) withactual fun myRememberSaveable(...) = remember(...) on all platforms and only one real implementation on androidMain sourceSet: actual fun myRememberSaveable() = rememberSaveable(...)

Thanks for your reply.
Imo, using rememberSavable() with rememberSaveableStateHolder() is useful in navigation pattern.
It allows state of a composable can be saved and restored (via Bundle on Android and in-memory on other platforms).

I cannot achieve that by using remember and rememberSaveableStateHolder

@hoc081098
Copy link
Author

hoc081098 commented Aug 18, 2023

Originally posted by @syt0r in #1932 (comment)

I did some investigation and looks like rememberSaveable actually works, but you need to implement additional thing to make it work, it's just that android's navigation library already has it implemented underneath. Also on desktop serialization is not really is necessary since everything is stored in memory

To make it work you need to create instance of SaveableStateHolder with rememberSaveableStateHolder() and wrap you navigation destinations with stateHolder.SaveableStateProvider(stringKey) { content }, it will assosiate your content with key and save data for specific destinations, then when removing destination you just need to invoke SaveableStateHolder.removeState(key)

Here is snippet of what I did in my project:

interface MultiplatformMainNavigationState : MainNavigationState {
    val currentDestination: State<MainDestination>
    val stateHolder: SaveableStateHolder
}

@Composable
fun MultiplatformMainNavigation(
    state: MainNavigationState
) {

    state as MultiplatformMainNavigationState

    val destination = state.currentDestination.value

    state.stateHolder.SaveableStateProvider(destination.toString()) {
        when (destination) {
            MainDestination.Home -> {
                val homeNavigationState = rememberHomeNavigationState()
                HomeScreen(
                    viewModel = getMultiplatformViewModel(),
                    mainNavigationState = state,
                    homeNavigationState = homeNavigationState
                )
            }
            MainDestination.About -> {
                AboutScreen(
                    mainNavigationState = state,
                    viewModel = getMultiplatformViewModel()
                )
            }
            // ...others
        }
    }

}

@Composable
fun rememberMultiplatformMainNavigationState(): MainNavigationState {
    val stack = remember { mutableStateOf<List<MainDestination>>(listOf(MainDestination.Home)) }
    val currentDestinationState = remember { derivedStateOf { stack.value.last() } }

    val stateHolder = rememberSaveableStateHolder()

    return remember {
        object : MultiplatformMainNavigationState {

            override val currentDestination = currentDestinationState
            override val stateHolder: SaveableStateHolder = stateHolder

            override fun navigateBack() {
                val lastItem = stack.value.last()
                stack.value = stack.value.dropLast(1)
                stateHolder.removeState(lastItem.toString())
            }

            override fun popUpToHome() {
                val itemsToRemove = stack.value.drop(1)
                stack.value = stack.value.take(1)
                itemsToRemove.forEach { stateHolder.removeState(it) }
            }

            override fun navigate(destination: MainDestination) {
                stack.value = stack.value.plus(destination)
            }

        }
    }
}

@hoc081098
Copy link
Author

Closed by #3899

@okushnikov
Copy link
Collaborator

Please check the following ticket on YouTrack for follow-ups to this issue. GitHub issues will be closed in the coming weeks.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request runtime Compose runtime problem
Projects
None yet
Development

No branches or pull requests

5 participants