https://kotlinlang.org logo
#compose
Title
# compose
m

Marko Novakovic

04/20/2022, 12:47 PM
Copy code
private fun <T : Any> SavedStateHandle.saveableMutableStateOf(
    key: String,
    saver: Saver<T, out Any> = autoSaver(),
    init: () -> T,
): MutableState<T> {
    @Suppress("UNCHECKED_CAST")
    (saver as Saver<T, Any>)
    val value = mutableStateOf(restoreOrInit(key, saver, init))
    saveToStateHandle(key, saver, value)
    return value
}

private fun <T : Any> SavedStateHandle.restoreOrInit(
    key: String,
    saver: Saver<T, Any>,
    init: () -> T,
): T = run {
    val restored = get<Bundle>(key)?.get("value")?.let(saver::restore)
    restored ?: init()
}

private fun <T : Any> SavedStateHandle.saveToStateHandle(
    key: String,
    saver: Saver<T, Any>,
    value: MutableState<T>,
) = setSavedStateProvider(key) {
    val saverScope = SaverScope { true }
    with(saver) {
        bundleOf("value" to saverScope.save(value.value))
    }
}

...
//usage
private var _state by savedStateHandle.saveableMutableStateOf(STATE) { initialState }
this used to work but now in
1.2.0-alpha07
setting
_state
doesn’t save value to
SavedStateHandle
a

Alex Vanyo

04/20/2022, 10:43 PM
How are you checking whether the value is saved to the
SavedStateHandle
? The saved state provider utility will only save the value when the entire
SavedStateHandle
is being saved, so just setting
_state
won’t immediately change what is stored in the
SavedStateHandle
. Also the latest versions of
androidx.lifecycle
(
2.5.0-beta01
was just released!) now includes some of these utilities that you can use.
m

Marko Novakovic

04/21/2022, 10:56 AM
I don’t quite understand what you are trying to say. btw, are there any examples of how can I bridge
SavedStateHandle
and
MutableState
?
this is how I use this extension, but it worked and idk when it just stopped working. I ran my unit tests and this one was failing. then I ran the app and tested and state is not neither saved nor restored
Copy code
abstract class StateStore<State : Any>(
    savedStateHandle: SavedStateHandle,
    initialState: State,
) : ViewModel() {

    private var _state: State by savedStateHandle.saveableMutableStateOf(STATE) { initialState }
    val state: State
        get() = _state

    fun updateState(reducer: State.() -> State) {
        _state = state.reducer()
    }

    companion object {
        private const val STATE = "state"
    }
}
a

Alex Vanyo

04/21/2022, 9:13 PM
In unit tests how are you checking saved state? And yep! There are examples in the docs here using the new built-in versions of these utilities: https://developer.android.com/reference/kotlin/androidx/lifecycle/SavedStateHandle#(androidx.lifecycle.SavedStateH[…]aveable.Saver,kotlin.Function0)
m

Marko Novakovic

04/22/2022, 2:04 PM
Copy code
private var _state: State by savedStateHandle.saveable(STATE) { mutableStateOf(initialState) }
    val state: State
        get() = _state
this doesn’t work, am I doing it right? that’s how it is in the docs. I tried with the app, not unit tests this time
a

Alex Vanyo

04/22/2022, 5:50 PM
Yeah, that should work it seems… can you open up a bug with a reproducing sample for us to take a look at?
m

Marko Novakovic

04/22/2022, 7:20 PM
I will, thanks for the link
4 Views