Skip to content

Instantly share code, notes, and snippets.

@Aidanvii7
Last active March 10, 2022 17:26
Show Gist options
  • Save Aidanvii7/1eb5d919a60a5441a6ec05e6f3f2de8d to your computer and use it in GitHub Desktop.
Save Aidanvii7/1eb5d919a60a5441a6ec05e6f3f2de8d to your computer and use it in GitHub Desktop.
compose utils
package com.example
import androidx.compose.runtime.Composable
import androidx.compose.runtime.MutableState
import androidx.compose.runtime.State
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.remember
import androidx.compose.ui.platform.LocalLifecycleOwner
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.Lifecycle.State.CREATED
import androidx.lifecycle.Lifecycle.State.STARTED
import androidx.lifecycle.flowWithLifecycle
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.flow
@Composable
fun <T> StateFlow<T>.collectAsStateWhileCreated(): State<T> =
collectAsStateWhile(minActiveState = CREATED)
@Composable
fun <T> StateFlow<T>.collectAsStateWhileStarted(): State<T> =
collectAsStateWhile(minActiveState = STARTED)
@Composable
fun <T> MutableStateFlow<T>.collectAsMutableStateWhileCreated(): MutableState<T> =
collectAsMutableStateWhile(minActiveState = CREATED)
@Composable
fun <T> MutableStateFlow<T>.collectAsMutableStateWhileStarted(): MutableState<T> =
collectAsMutableStateWhile(minActiveState = STARTED)
@Composable
fun <T> StateFlow<T>.collectAsStateWhile(
minActiveState: Lifecycle.State,
): State<T> = collectAsStateWhile(
minActiveState = minActiveState,
default = remember { value },
)
@Composable
fun <T> MutableStateFlow<T>.collectAsMutableStateWhile(
minActiveState: Lifecycle.State,
): MutableState<T> = collectAsMutableStateWhile(
minActiveState = minActiveState,
default = remember { value },
)
@Composable
fun <T> Flow<T>.collectAsStateWhileCreated(
default: T,
): State<T> = collectAsStateWhile(
minActiveState = CREATED,
default = default,
)
@Composable
fun <T> Flow<T>.collectAsStateWhileStarted(
default: T,
): State<T> = collectAsStateWhile(
minActiveState = STARTED,
default = default,
)
@Composable
fun <T> Flow<T>.collectAsStateWhile(
minActiveState: Lifecycle.State,
default: T,
): State<T> {
@Suppress("NON_EXHAUSTIVE_WHEN")
when (minActiveState) {
Lifecycle.State.INITIALIZED,
Lifecycle.State.DESTROYED,
-> {
throw IllegalArgumentException("Only supports lifecycle states CREATED, STARTED and RESUMED")
}
}
val lifecycleOwner = LocalLifecycleOwner.current
return remember(this, default, lifecycleOwner) {
flowWithLifecycle(
lifecycle = lifecycleOwner.lifecycle,
minActiveState = minActiveState,
)
}.collectAsState(initial = default)
}
@Composable
fun <T> MutableStateFlow<T>.collectAsMutableStateWhile(
minActiveState: Lifecycle.State,
default: T,
): MutableState<T> {
@Suppress("NON_EXHAUSTIVE_WHEN")
when (minActiveState) {
Lifecycle.State.INITIALIZED,
Lifecycle.State.DESTROYED,
-> {
throw IllegalArgumentException("Only supports lifecycle states CREATED, STARTED and RESUMED")
}
}
val lifecycleOwner = LocalLifecycleOwner.current
val state: State<T> = remember(this, default, lifecycleOwner) {
flowWithLifecycle(
lifecycle = lifecycleOwner.lifecycle,
minActiveState = minActiveState,
)
}.collectAsState(initial = default)
val mutableState: MutableState<T> = remember(state) {
object : MutableState<T> {
override var value: T
get() = state.value
set(value) {
this@collectAsMutableStateWhile.value = value
}
override operator fun component1(): T = value
override operator fun component2(): (T) -> Unit = { value = it }
}
}
return mutableState
}
@Composable
fun <T> (suspend () -> T).asStateWhileCreated(
default: T,
): State<T> = asStateWhile(
minActiveState = CREATED,
default = default,
)
@Composable
fun <T> (suspend () -> T).asStateWhileStarted(
default: T,
): State<T> = asStateWhile(
minActiveState = STARTED,
default = default,
)
@Composable
fun <T> (suspend () -> T).asStateWhile(
minActiveState: Lifecycle.State,
default: T,
): State<T> = remember(this) {
flow {
val value: T = invoke()
emit(value)
}
}.collectAsStateWhile(
minActiveState = minActiveState,
default = default,
)
package com.example
import androidx.compose.runtime.Composable
import androidx.compose.runtime.DisallowComposableCalls
import androidx.compose.runtime.MutableState
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import java.util.concurrent.atomic.AtomicBoolean
@Composable
inline fun <T> rememberMutable(
calculation: @DisallowComposableCalls () -> T,
): MutableState<T> = remember { mutableStateOf(calculation()) }
@Composable
inline fun <T> rememberMutable(
key: Any?,
calculation: @DisallowComposableCalls () -> T,
): MutableState<T> {
val current: MutableState<T> = remember { mutableStateOf(calculation()) }
val firstRun: AtomicBoolean = remember { AtomicBoolean(true) }
remember<Any?>(key) {
if (firstRun.getAndSet(false)) return@remember
current.value = calculation()
}
return current
}
@Composable
inline fun <T> rememberMutable(
key1: Any?,
key2: Any?,
calculation: @DisallowComposableCalls () -> T,
): MutableState<T> {
val current: MutableState<T> = remember { mutableStateOf(calculation()) }
val firstRun: AtomicBoolean = remember { AtomicBoolean(true) }
remember<Any?>(key1, key2) {
if (firstRun.getAndSet(false)) return@remember
current.value = calculation()
}
return current
}
@Composable
inline fun <T> rememberMutable(
key1: Any?,
key2: Any?,
key3: Any?,
calculation: @DisallowComposableCalls () -> T,
): MutableState<T> {
val current: MutableState<T> = remember { mutableStateOf(calculation()) }
val firstRun: AtomicBoolean = remember { AtomicBoolean(true) }
remember<Any?>(key1, key2, key3) {
if (firstRun.getAndSet(false)) return@remember
current.value = calculation()
}
return current
}
@Composable
inline fun <T> rememberMutable(
vararg keys: Any?,
calculation: @DisallowComposableCalls () -> T,
): MutableState<T> {
val current: MutableState<T> = remember { mutableStateOf(calculation()) }
val firstRun: AtomicBoolean = remember { AtomicBoolean(true) }
remember<Any?>(*keys) {
if (firstRun.getAndSet(false)) return@remember
current.value = calculation()
}
return current
}
@Composable
inline fun <T, R> T.remembered(
calculation: @DisallowComposableCalls T.() -> R,
): R = remember(this) {
calculation()
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment