commonMain.androidx.compose.runtime.ProduceState.kt Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of runtime Show documentation
Show all versions of runtime Show documentation
Tree composition support for code generated by the Compose compiler plugin and corresponding public API
The newest version!
/*
* Copyright 2021 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.
*/
@file:JvmName("SnapshotStateKt")
@file:JvmMultifileClass
package androidx.compose.runtime
import kotlin.coroutines.CoroutineContext
import kotlin.jvm.JvmMultifileClass
import kotlin.jvm.JvmName
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.suspendCancellableCoroutine
/**
* Receiver scope for use with [produceState].
*/
interface ProduceStateScope : MutableState, CoroutineScope {
/**
* Await the disposal of this producer whether it left the composition,
* the source changed, or an error occurred. Always runs [onDispose] before resuming.
*
* This method is useful when configuring callback-based state producers that do not suspend,
* for example:
*
* @sample androidx.compose.runtime.samples.ProduceStateAwaitDispose
*/
suspend fun awaitDispose(onDispose: () -> Unit): Nothing
}
private class ProduceStateScopeImpl(
state: MutableState,
override val coroutineContext: CoroutineContext
) : ProduceStateScope, MutableState by state {
override suspend fun awaitDispose(onDispose: () -> Unit): Nothing {
try {
suspendCancellableCoroutine { }
} finally {
onDispose()
}
}
}
/**
* Return an observable [snapshot][androidx.compose.runtime.snapshots.Snapshot] [State] that
* produces values over time without a defined data source.
*
* [producer] is launched when [produceState] enters the composition and is cancelled when
* [produceState] leaves the composition. [producer] should use [ProduceStateScope.value]
* to set new values on the returned [State].
*
* The returned [State] conflates values; no change will be observable if
* [ProduceStateScope.value] is used to set a value that is [equal][Any.equals] to its old value,
* and observers may only see the latest value if several values are set in rapid succession.
*
* [produceState] may be used to observe either suspending or non-suspending sources of external
* data, for example:
*
* @sample androidx.compose.runtime.samples.ProduceState
*
* @sample androidx.compose.runtime.samples.ProduceStateAwaitDispose
*/
@Composable
fun produceState(
initialValue: T,
producer: suspend ProduceStateScope.() -> Unit
): State {
val result = remember { mutableStateOf(initialValue) }
LaunchedEffect(Unit) {
ProduceStateScopeImpl(result, coroutineContext).producer()
}
return result
}
/**
* Return an observable [snapshot][androidx.compose.runtime.snapshots.Snapshot] [State] that
* produces values over time from [key1].
*
* [producer] is launched when [produceState] enters the composition and is cancelled when
* [produceState] leaves the composition. If [key1] changes, a running [producer] will be
* cancelled and re-launched for the new source. [producer] should use [ProduceStateScope.value]
* to set new values on the returned [State].
*
* The returned [State] conflates values; no change will be observable if
* [ProduceStateScope.value] is used to set a value that is [equal][Any.equals] to its old value,
* and observers may only see the latest value if several values are set in rapid succession.
*
* [produceState] may be used to observe either suspending or non-suspending sources of external
* data, for example:
*
* @sample androidx.compose.runtime.samples.ProduceState
*
* @sample androidx.compose.runtime.samples.ProduceStateAwaitDispose
*/
@Composable
fun produceState(
initialValue: T,
key1: Any?,
producer: suspend ProduceStateScope.() -> Unit
): State {
val result = remember { mutableStateOf(initialValue) }
LaunchedEffect(key1) {
ProduceStateScopeImpl(result, coroutineContext).producer()
}
return result
}
/**
* Return an observable [snapshot][androidx.compose.runtime.snapshots.Snapshot] [State] that
* produces values over time from [key1] and [key2].
*
* [producer] is launched when [produceState] enters the composition and is cancelled when
* [produceState] leaves the composition. If [key1] or [key2] change, a running [producer]
* will be cancelled and re-launched for the new source. [producer] should use
* [ProduceStateScope.value] to set new values on the returned [State].
*
* The returned [State] conflates values; no change will be observable if
* [ProduceStateScope.value] is used to set a value that is [equal][Any.equals] to its old value,
* and observers may only see the latest value if several values are set in rapid succession.
*
* [produceState] may be used to observe either suspending or non-suspending sources of external
* data, for example:
*
* @sample androidx.compose.runtime.samples.ProduceState
*
* @sample androidx.compose.runtime.samples.ProduceStateAwaitDispose
*/
@Composable
fun produceState(
initialValue: T,
key1: Any?,
key2: Any?,
producer: suspend ProduceStateScope.() -> Unit
): State {
val result = remember { mutableStateOf(initialValue) }
LaunchedEffect(key1, key2) {
ProduceStateScopeImpl(result, coroutineContext).producer()
}
return result
}
/**
* Return an observable [snapshot][androidx.compose.runtime.snapshots.Snapshot] [State] that
* produces values over time from [key1], [key2] and [key3].
*
* [producer] is launched when [produceState] enters the composition and is cancelled when
* [produceState] leaves the composition. If [key1], [key2] or [key3] change, a running
* [producer] will be cancelled and re-launched for the new source. [producer should use
* [ProduceStateScope.value] to set new values on the returned [State].
*
* The returned [State] conflates values; no change will be observable if
* [ProduceStateScope.value] is used to set a value that is [equal][Any.equals] to its old value,
* and observers may only see the latest value if several values are set in rapid succession.
*
* [produceState] may be used to observe either suspending or non-suspending sources of external
* data, for example:
*
* @sample androidx.compose.runtime.samples.ProduceState
*
* @sample androidx.compose.runtime.samples.ProduceStateAwaitDispose
*/
@Composable
fun produceState(
initialValue: T,
key1: Any?,
key2: Any?,
key3: Any?,
producer: suspend ProduceStateScope.() -> Unit
): State {
val result = remember { mutableStateOf(initialValue) }
LaunchedEffect(key1, key2, key3) {
ProduceStateScopeImpl(result, coroutineContext).producer()
}
return result
}
/**
* Return an observable [snapshot][androidx.compose.runtime.snapshots.Snapshot] [State] that
* produces values over time from [keys].
*
* [producer] is launched when [produceState] enters the composition and is cancelled when
* [produceState] leaves the composition. If [keys] change, a running [producer] will be
* cancelled and re-launched for the new source. [producer] should use [ProduceStateScope.value]
* to set new values on the returned [State].
*
* The returned [State] conflates values; no change will be observable if
* [ProduceStateScope.value] is used to set a value that is [equal][Any.equals] to its old value,
* and observers may only see the latest value if several values are set in rapid succession.
*
* [produceState] may be used to observe either suspending or non-suspending sources of external
* data, for example:
*
* @sample androidx.compose.runtime.samples.ProduceState
*
* @sample androidx.compose.runtime.samples.ProduceStateAwaitDispose
*/
@Composable
fun produceState(
initialValue: T,
vararg keys: Any?,
producer: suspend ProduceStateScope.() -> Unit
): State {
val result = remember { mutableStateOf(initialValue) }
@Suppress("CHANGING_ARGUMENTS_EXECUTION_ORDER_FOR_NAMED_VARARGS")
LaunchedEffect(keys = keys) {
ProduceStateScopeImpl(result, coroutineContext).producer()
}
return result
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy