[go: nahoru, domu]

blob: 2317477cc58ac4bf7bc406765f47d51b0afc0f6d [file] [log] [blame]
/*
* Copyright 2020 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package androidx.compose.runtime.savedinstancestate
import androidx.compose.Composable
import androidx.compose.MutableState
import androidx.compose.SnapshotMutationPolicy
import androidx.compose.mutableStateOf
import androidx.compose.referentialEqualityPolicy
import androidx.compose.state
/**
* Used to introduce a state value of type [T] into a composition.
*
* It behaves similarly to [state], but the stored value will survive the activity or process
* recreation using the saved instance state mechanism (for example it happens when the screen is
* rotated in the Android application).
*
* @sample androidx.compose.runtime.savedinstancestate.samples.SavedInstanceStateSample
*
* This function works nicely with immutable values as we wrap them into [MutableState] and
* update the values in this state. If you work with a mutable object and going to update the
* state of this object instead of recreating it [rememberSavedInstanceState] can suit you more.
*
* If you use it with types which can be stored inside the Bundle then it will be saved and
* restored automatically using [autoSaver], otherwise you will need to provide a custom [Saver]
* implementation via the [saver] param.
*
* @sample androidx.compose.runtime.savedinstancestate.samples.CustomSaverSample
*
* @param inputs A set of inputs such that, when any of them have changed, will cause the state to
* reset and [init] to be rerun
* @param saver The [Saver] object which defines how the state is saved and restored.
* @param key An optional key to be used as a key for the saved value. If not provided we use the
* automatically generated by the Compose runtime which is unique for the every exact code location
* in the composition tree
* @param policy a callback to compare the previous and new instance of [T] when
* [MutableState.value] is written to. The policy is used to determine how composition should be
* scheduled. See [SnapshotMutationPolicy].
* @param init A factory function to create the initial value of this state
*/
@Composable
fun <T> savedInstanceState(
vararg inputs: Any?,
saver: Saver<T, out Any> = autoSaver(),
key: String? = null,
policy: SnapshotMutationPolicy<T> = referentialEqualityPolicy(),
init: () -> T
): MutableState<T> = rememberSavedInstanceState(
*inputs,
saver = mutableStateSaver(saver, policy),
key = key,
init = { mutableStateOf(init(), policy) }
)
private fun <T> mutableStateSaver(
inner: Saver<T, out Any>,
policy: SnapshotMutationPolicy<T>
) = Saver<MutableState<T>, Any>(
save = { state ->
with(inner) {
val value = state.value
if (value == null) {
EmptyStateValue
} else {
save(value)
}
}
},
restore = @Suppress("UNCHECKED_CAST") {
val restored = if (it == EmptyStateValue) {
null
} else {
(inner as Saver<T, Any>).restore(it)
}
mutableStateOf(restored as T, policy)
}
)
/**
* The object we save to indicate that we will need to restore the state with a null value.
*/
private val EmptyStateValue = "[NullValuePlacedInsideTheMutableState]"