Last active
December 9, 2022 00:29
-
-
Save kmerrell42/7cb71db700bffcfd6a42b27c02553084 to your computer and use it in GitHub Desktop.
Composable effects for the Android Lifecycle (onCreate, onResume, onPause, etc)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package io.mercury.android.coroutines.lifecycle | |
import androidx.compose.runtime.Composable | |
import androidx.compose.runtime.DisposableEffect | |
import androidx.compose.runtime.rememberCoroutineScope | |
import androidx.compose.ui.platform.LocalLifecycleOwner | |
import androidx.lifecycle.Lifecycle | |
import androidx.lifecycle.Lifecycle.Event.ON_CREATE | |
import androidx.lifecycle.Lifecycle.Event.ON_DESTROY | |
import androidx.lifecycle.Lifecycle.Event.ON_PAUSE | |
import androidx.lifecycle.Lifecycle.Event.ON_RESUME | |
import androidx.lifecycle.Lifecycle.Event.ON_START | |
import androidx.lifecycle.Lifecycle.Event.ON_STOP | |
import androidx.lifecycle.LifecycleEventObserver | |
import kotlinx.coroutines.CoroutineScope | |
import kotlinx.coroutines.Job | |
import kotlinx.coroutines.launch | |
/** | |
* Effect with a lifecycle window from @param launchOnEvent to @param disposeOnEvent. The provided | |
* @param block will be called during the lifecycle window in a coroutine Job that will get | |
* cancelled at the end or when the composition is disposed. | |
* | |
* The effect runs on the MainDispatcher. | |
* | |
* @param launchOnEvent The event to start the effect | |
* @param disposeOnEvent The event to stop the effect, if null, the effect will run until the Composable is disposed | |
* @param block The block that runs during the lifecycle window | |
*/ | |
@Composable | |
fun LifecycleEffect( | |
launchOnEvent: Lifecycle.Event, | |
disposeOnEvent: Lifecycle.Event? = null, | |
block: suspend CoroutineScope.() -> Unit | |
) { | |
val lifecycleOwner = LocalLifecycleOwner.current | |
val scope = rememberCoroutineScope() | |
DisposableEffect(lifecycleOwner) { | |
var job: Job? = null | |
val observer = LifecycleEventObserver { _, event -> | |
if (event == launchOnEvent) { | |
job?.cancel() | |
job = scope.launch { block() } | |
} else if (event == disposeOnEvent) { | |
job?.cancel() | |
} | |
} | |
lifecycleOwner.lifecycle.addObserver(observer) | |
// Cleanup | |
onDispose { | |
job?.cancel() | |
lifecycleOwner.lifecycle.removeObserver(observer) | |
} | |
} | |
} | |
/** | |
* LifecycleEffect that will launch on onCreate and dispose on onDestroy. | |
*/ | |
@Composable | |
fun CreatedEffect(block: suspend CoroutineScope.() -> Unit) { | |
LifecycleEffect(ON_CREATE, block = block) | |
} | |
@Composable | |
fun WhileCreatedEffect(block: suspend CoroutineScope.() -> Unit) { | |
LifecycleEffect(ON_CREATE, ON_DESTROY, block = block) | |
} | |
@Composable | |
fun StartedEffect(block: suspend CoroutineScope.() -> Unit) { | |
LifecycleEffect(ON_START, block = block) | |
} | |
@Composable | |
fun WhileStartedEffect(block: suspend CoroutineScope.() -> Unit) { | |
LifecycleEffect(ON_START, ON_STOP, block = block) | |
} | |
@Composable | |
fun ResumedEffect(block: suspend CoroutineScope.() -> Unit) { | |
LifecycleEffect(ON_RESUME, block = block) | |
} | |
@Composable | |
fun WhileResumedEffect(block: suspend CoroutineScope.() -> Unit) { | |
LifecycleEffect(ON_RESUME, ON_PAUSE, block = block) | |
} | |
@Composable | |
fun PausedEffect(block: suspend CoroutineScope.() -> Unit) { | |
LifecycleEffect(ON_PAUSE, block = block) | |
} | |
@Composable | |
fun StoppedEffect(block: suspend CoroutineScope.() -> Unit) { | |
LifecycleEffect(ON_STOP, block = block) | |
} | |
@Composable | |
fun DestroyedEffect(onEvent: suspend CoroutineScope.() -> Unit) { | |
LifecycleEffect(ON_DESTROY, block = onEvent) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment