Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

StateFlowExtesions #127

Closed
wants to merge 9 commits into from
Expand Up @@ -35,7 +35,7 @@ import org.orbitmvi.orbit.ContainerHost
*/
@SuppressLint("ComposableNaming")
@Composable
public fun <STATE : Any, SIDE_EFFECT : Any> ContainerHost<STATE, SIDE_EFFECT>.collectSideEffect(
fun <STATE : Any, SIDE_EFFECT : Any> ContainerHost<STATE, SIDE_EFFECT>.collectSideEffect(
lifecycleState: Lifecycle.State = Lifecycle.State.STARTED,
sideEffect: (suspend (sideEffect: SIDE_EFFECT) -> Unit)
) {
Expand All @@ -55,7 +55,7 @@ public fun <STATE : Any, SIDE_EFFECT : Any> ContainerHost<STATE, SIDE_EFFECT>.co
*/
@SuppressLint("ComposableNaming")
@Composable
public fun <STATE : Any, SIDE_EFFECT : Any> ContainerHost<STATE, SIDE_EFFECT>.collectState(
fun <STATE : Any, SIDE_EFFECT : Any> ContainerHost<STATE, SIDE_EFFECT>.collectState(
lifecycleState: Lifecycle.State = Lifecycle.State.STARTED,
state: (suspend (state: STATE) -> Unit)
) {
Expand All @@ -74,7 +74,7 @@ public fun <STATE : Any, SIDE_EFFECT : Any> ContainerHost<STATE, SIDE_EFFECT>.co
* @param lifecycleState The Lifecycle where the restarting collecting from this flow work will be kept alive.
*/
@Composable
public fun <STATE : Any, SIDE_EFFECT : Any> ContainerHost<STATE, SIDE_EFFECT>.collectAsState(
fun <STATE : Any, SIDE_EFFECT : Any> ContainerHost<STATE, SIDE_EFFECT>.collectAsState(
lifecycleState: Lifecycle.State = Lifecycle.State.STARTED
): State<STATE> {
val stateFlow = container.stateFlow
Expand Down
@@ -0,0 +1,87 @@
/*
* Copyright 2021-2022 Mikołaj Leszczyński & Appmattus Limited
*
* 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 org.orbitmvi.orbit.compose

import android.annotation.SuppressLint
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
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.flowWithLifecycle
import androidx.lifecycle.repeatOnLifecycle
import kotlinx.coroutines.flow.StateFlow

/**
* Observe [StateFlow] of [SideEffectFlow] in a Compose [LaunchedEffect].
* @param lifecycleState [Lifecycle.State] in which [state] block runs.
*/
@SuppressLint("ComposableNaming")
@Composable
fun <SIDE_EFFECT : Any> StateFlow<SIDE_EFFECT>.collectSideEffectLifecycleAware(
lifecycleState: Lifecycle.State = Lifecycle.State.STARTED,
sideEffect: (suspend (sideEffect: SIDE_EFFECT) -> Unit)
) {
val sideEffectFlow = this
val lifecycleOwner = LocalLifecycleOwner.current

LaunchedEffect(sideEffectFlow, lifecycleOwner) {
lifecycleOwner.lifecycle.repeatOnLifecycle(lifecycleState) {
sideEffectFlow.collect { sideEffect(it) }
}
}
}

/**
* Observe [StateFlow] of [STATE] in a Compose [LaunchedEffect].
* @param lifecycleState [Lifecycle.State] in which [state] block runs.
*/
@SuppressLint("ComposableNaming")
@Composable
fun <STATE : Any> StateFlow<STATE>.collectStateLifecycleAware(
lifecycleState: Lifecycle.State = Lifecycle.State.STARTED,
state: (suspend (state: STATE) -> Unit)
) {
val stateFlow = this
val lifecycleOwner = LocalLifecycleOwner.current

LaunchedEffect(stateFlow, lifecycleOwner) {
lifecycleOwner.lifecycle.repeatOnLifecycle(lifecycleState) {
stateFlow.collect { state(it) }
}
}
}

/**
* Observe [StateFlow] of [STATE] as [State].
* @param lifecycleState The Lifecycle where the restarting collecting from this flow work will be kept alive.
*/
@Composable
fun <STATE : Any> StateFlow<STATE>.collectAsStateLifecycleAware(
lifecycleState: Lifecycle.State = Lifecycle.State.STARTED
): State<STATE> {
val lifecycleOwner = LocalLifecycleOwner.current
val stateFlowLifecycleAware = remember(this, lifecycleOwner) {
this.flowWithLifecycle(lifecycleOwner.lifecycle, lifecycleState)
}
// Need to access the initial value to convert to State - collectAsState() suppresses this lint warning too
@SuppressLint("StateFlowValueCalledInComposition")
val initialValue = this.value
return stateFlowLifecycleAware.collectAsState(initialValue)
}