Last active
January 1, 2022 20:34
-
-
Save cbeyls/86f18a64b44fff51bc02ff6f82606923 to your computer and use it in GitHub Desktop.
A LifecycleOwner composed of children LifecycleOwners
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 be.digitalia.utils | |
import android.os.Handler | |
import android.os.Looper | |
import androidx.lifecycle.Lifecycle | |
import androidx.lifecycle.LifecycleEventObserver | |
import androidx.lifecycle.LifecycleObserver | |
import androidx.lifecycle.LifecycleOwner | |
import androidx.lifecycle.LifecycleRegistry | |
import java.io.Closeable | |
/** | |
* A LifecycleOwner composed of children LifecycleOwners. | |
* Its state moves to STARTED when a least one child Lifecycle is at least in the STARTED state. | |
* Its state moves to CREATED when no child Lifecycle is at least in the STARTED state. | |
* Its state moves to DESTROYED when close() is called. The instance cannot be used afterwards. | |
*/ | |
class CompositeLifecycleOwner(private val stopTimeoutMillis: Long = 1000L) : LifecycleOwner, Closeable { | |
private val registry = LifecycleRegistry(this).apply { | |
currentState = Lifecycle.State.CREATED | |
} | |
private val handler = Handler(Looper.getMainLooper()) | |
private val children = mutableSetOf<LifecycleOwner>() | |
private var startedCount = 0 | |
private val lifecycleObserver: LifecycleObserver = LifecycleEventObserver { source, event -> | |
when (event) { | |
Lifecycle.Event.ON_START -> incrementStartedCount() | |
Lifecycle.Event.ON_STOP -> decrementStartedCount() | |
Lifecycle.Event.ON_DESTROY -> children.remove(source) | |
else -> Unit | |
} | |
} | |
private val onStopRunnable = Runnable { | |
registry.currentState = Lifecycle.State.CREATED | |
} | |
private fun incrementStartedCount() { | |
if (++startedCount == 1) { | |
handler.removeCallbacks(onStopRunnable) | |
registry.currentState = Lifecycle.State.STARTED | |
} | |
} | |
private fun decrementStartedCount() { | |
if (--startedCount == 0) { | |
handler.postDelayed(onStopRunnable, stopTimeoutMillis) | |
} | |
} | |
override fun getLifecycle(): Lifecycle = registry | |
operator fun plusAssign(child: LifecycleOwner) { | |
require(child != this) | |
check(registry.currentState >= Lifecycle.State.CREATED) | |
if (children.add(child)) { | |
child.lifecycle.addObserver(lifecycleObserver) | |
} | |
} | |
operator fun minusAssign(child: LifecycleOwner) { | |
if (children.remove(child)) { | |
val lifecycle = child.lifecycle | |
lifecycle.removeObserver(lifecycleObserver) | |
if (lifecycle.currentState >= Lifecycle.State.STARTED) { | |
decrementStartedCount() | |
} | |
} | |
} | |
override fun close() { | |
handler.removeCallbacks(onStopRunnable) | |
for (child in children) { | |
child.lifecycle.removeObserver(lifecycleObserver) | |
} | |
children.clear() | |
startedCount = 0 | |
registry.currentState = Lifecycle.State.DESTROYED | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment