| /* |
| * 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.runtime.Composable |
| import androidx.compose.runtime.MutableState |
| import androidx.compose.runtime.SnapshotMutationPolicy |
| import androidx.compose.runtime.mutableStateOf |
| import androidx.compose.runtime.referentialEqualityPolicy |
| import androidx.compose.runtime.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]" |