Skip to content

Instantly share code, notes, and snippets.

@skydoves
Last active September 19, 2024 11:24
Show Gist options
  • Save skydoves/5b4d44968c2c1d47aea381e9679f8af3 to your computer and use it in GitHub Desktop.
Save skydoves/5b4d44968c2c1d47aea381e9679f8af3 to your computer and use it in GitHub Desktop.
RestartableStateFlow
// RestartableStateFlow that allows you to re-run the execution
interface RestartableStateFlow<out T> : StateFlow<T> {
fun restart()
}
interface SharingRestartable : SharingStarted {
fun restart()
}
// impementation of the sharing restartable
private data class SharingRestartableImpl(
private val sharingStarted: SharingStarted,
) : SharingRestartable {
private val restartFlow = MutableSharedFlow<SharingCommand>(extraBufferCapacity = 2)
// combine the commands from the restartFlow and the subscriptionCount
override fun command(subscriptionCount: StateFlow<Int>): Flow<SharingCommand> {
return merge(restartFlow, sharingStarted.command(subscriptionCount))
}
// stop and reset the replay cache and restart
override fun restart() {
restartFlow.tryEmit(SharingCommand.STOP_AND_RESET_REPLAY_CACHE)
restartFlow.tryEmit(SharingCommand.START)
}
}
// create a hot flow, which is restartable by manually from a cold flow
fun <T> Flow<T>.restartableStateIn(
scope: CoroutineScope,
started: SharingStarted,
initialValue: T
): RestartableStateFlow<T> {
val sharingRestartable = SharingRestartableImpl(started)
val stateFlow = stateIn(scope, sharingRestartable, initialValue)
return object : RestartableStateFlow<T>, StateFlow<T> by stateFlow {
override fun restart() = sharingRestartable.restart()
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment