Skip to content

Instantly share code, notes, and snippets.

@hansenji
Created December 31, 2020 19:18
Show Gist options
  • Save hansenji/17972c06b8bf58977636e2e0e9601c7c to your computer and use it in GitHub Desktop.
Save hansenji/17972c06b8bf58977636e2e0e9601c7c to your computer and use it in GitHub Desktop.
Collect flows tied to the Lifecycle
class LifecycleGroup(val lifecycleOwner: LifecycleOwner) {
/**
* Recommended for the majority of use cases
* The crucial difference from [collect] is that when the original flow emits a new value, [block] for previous
* value is cancelled.
**/
inline fun <T> Flow<T>.collectLatestWhenStarted(crossinline block: suspend (T) -> Unit): Job {
return lifecycleOwner.lifecycleScope.launchWhenStarted {
this@collectLatestWhenStarted.collectLatest {
block(it)
}
}
}
/**
* Recommended for the majority of use cases
*/
inline fun <T> ReceiveChannel<T>.receiveWhenStarted(crossinline block: suspend (T) -> Unit): Job {
return lifecycleOwner.lifecycleScope.launchWhenStarted {
for (event in this@receiveWhenStarted) {
block(event)
}
}
}
/**
* Recommended for when every emit needs to be processed to completion.
*/
inline fun <T> Flow<T>.collectWhenStarted(crossinline block: suspend (T) -> Unit): Job {
return lifecycleOwner.lifecycleScope.launchWhenStarted {
this@collectWhenStarted.collect {
block(it)
}
}
}
/**
* Recommended for collecting inside a fragment in a viewpager when only the active fragment should receive events.
* If fragments need to be updated in the background use [collectLatestWhenStarted]
*/
inline fun <T> Flow<T>.collectLatestWhenResumed(crossinline block: suspend (T) -> Unit): Job {
return lifecycleOwner.lifecycleScope.launchWhenResumed {
this@collectLatestWhenResumed.collectLatest {
block(it)
}
}
}
/**
* Recommended for collecting inside a fragment in a viewpager and you need to process every emit to completion
*/
inline fun <T> Flow<T>.collectWhenResumed(crossinline block: suspend (T) -> Unit): Job {
return lifecycleOwner.lifecycleScope.launchWhenResumed {
this@collectWhenResumed.collect {
block(it)
}
}
}
/**
* Recommended for receiving inside a fragment in a viewpager as only the active Fragment will be affected.
*/
inline fun <T> ReceiveChannel<T>.receiveWhenResumed(crossinline block: suspend (T) -> Unit): Job {
return lifecycleOwner.lifecycleScope.launchWhenResumed {
for (e in this@receiveWhenResumed) {
block(e)
}
}
}
}
inline fun withLifecycleOwner(lifecycleOwner: LifecycleOwner, block: LifecycleGroup.() -> Unit) {
LifecycleGroup(lifecycleOwner).run(block)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment