@@ -30,6 +30,7 @@ import kotlinx.coroutines.flow.combine
3030import kotlinx.coroutines.flow.emptyFlow
3131import kotlinx.coroutines.flow.first
3232import kotlinx.coroutines.flow.flatMapLatest
33+ import kotlinx.coroutines.flow.flow
3334import kotlinx.coroutines.flow.flowOf
3435import kotlinx.coroutines.flow.map
3536import kotlinx.coroutines.flow.mapLatest
@@ -48,10 +49,15 @@ interface PauseManager : CoroutineContext.Element {
4849 companion object Key : CoroutineContext.Key<PauseManager>
4950}
5051
51- class LifecyclePauseManager (scope : CoroutineScope , source : LifecycleOwner , minimumState : Lifecycle .State )
52- : PauseManager {
53- override val isPaused = source.lifecycle.currentStateFlow.map { ! it.isAtLeast(minimumState) }
54- .stateIn(scope, WhileSubscribed (), ! source.lifecycle.currentState.isAtLeast(minimumState))
52+ class LifecyclePauseManager (
53+ scope : CoroutineScope , source : LifecycleOwner , minimumState : Lifecycle .State ,
54+ bypassFlow : Flow <Boolean >
55+ ) : PauseManager {
56+ @OptIn(ExperimentalCoroutinesApi ::class )
57+ override val isPaused = bypassFlow.flatMapLatest {
58+ if (it || true ) flowOf(false ) else
59+ source.lifecycle.currentStateFlow.map { ! it.isAtLeast(minimumState) } }
60+ .stateIn(scope, WhileSubscribed (), ! source.lifecycle.currentState.isAtLeast(minimumState))
5561}
5662
5763object EmptyPauseManager : PauseManager {
@@ -186,14 +192,30 @@ suspend fun <T> repeatUntilDoneWhenUnpaused(block: suspend () -> T): T {
186192
187193fun repeatPausingWithLifecycle (source : LifecycleOwner ,
188194 context : CoroutineContext = EmptyCoroutineContext ,
189- minimumStateForCollect : Lifecycle .State = Lifecycle .State .CREATED ,
195+ minimumStateForCollect : Lifecycle .State = Lifecycle .State .INITIALIZED ,
190196 minimumStateForUnpause : Lifecycle .State = Lifecycle .State .RESUMED ,
197+ initialUnpauseUntilResumeTimeoutMs : ULong = 2000U,
191198 block : suspend () -> Unit ) {
192- source.lifecycleScope.launch {
193- source.repeatOnLifecycle(minimumStateForCollect) {
194- withContext(context + LifecyclePauseManager (this , source, minimumStateForUnpause)) {
199+ val maxForceUnpausedTimestamp = System .currentTimeMillis() + initialUnpauseUntilResumeTimeoutMs.toLong()
200+ val bypass = flow {
201+ val timeLeft = maxForceUnpausedTimestamp - System .currentTimeMillis()
202+ if (timeLeft > 0 ) {
203+ emit(true )
204+ delay(timeLeft)
205+ }
206+ emit(false )
207+ }
208+ source.lifecycleScope.launch(context) {
209+ if (minimumStateForCollect == Lifecycle .State .INITIALIZED ) {
210+ withContext(context + LifecyclePauseManager (this , source, minimumStateForUnpause, bypass)) {
195211 block()
196212 }
213+ } else {
214+ source.repeatOnLifecycle(minimumStateForCollect) {
215+ withContext(context + LifecyclePauseManager (this , source, minimumStateForUnpause, bypass)) {
216+ block()
217+ }
218+ }
197219 }
198220 }
199221}
0 commit comments