I was expecting my next post to continue my series on dagger.android
, but today's adventures were too strange not to relate to others.
Need: a LiveData
object that would "do something" when it had an active observer.
Observation: LiveData
has two hooks: onActive()
and onInactive()
that are designed for just this purpose.
Plan: Extend MutableLiveData
with a class named ActiveMutableLiveData
that does something with these hooks.
Further observation: if I'm going to push this to production, I should test it to prove to myself I understand what's going on and that my new class behaves as expected.
ActiveMutableLiveData
/** * A form of [MutableLiveData][android.arch.lifecycle.MutableLiveData] that * provides hooks for for [onActive][android.arch.lifecycle.MutableLiveData.onActive] and * [onInactive][android.arch.lifecycle.MutableLiveData.onInactive]. Use these to be * notified when this [LiveData][android.arch.lifecycle.LiveData] gains and loses an * active observer. */ class ActiveMutableLiveData<T>( private val onActiveListener: OnActiveListener ) : MutableLiveData<T>() { constructor(onActive: () -> Unit = {}, onInactive: () -> Unit = {}) : this( onActiveListenerFromLambdas(onActive, onInactive) ) override fun onActive() { onActiveListener.onActive() } override fun onInactive() { onActiveListener.onInactive() } } fun onActiveListenerFromLambdas( onActive: () -> Unit, onInactive: () -> Unit ): OnActiveListener { return object : OnActiveListener { override fun onActive() { onActive.invoke() } override fun onInactive() { onInactive.invoke() } } } interface OnActiveListener { fun onActive() fun onInactive() }
ActiveMutableLiveDataTest
// Using JUnit5 internal class ActiveMutableLiveDataTest { private val counter = AtomicInteger() private val liveData = ActiveMutableLiveData<Boolean>(onActive = { counter.incrementAndGet() }) @Test fun whenObjectBecomesActive_thenOnActiveListenerIsTriggered() { // Given val lifecycle = TestLifecycle() liveData.observe(lifecycle, Observer { println("$it") }) // verify initial condition assertEquals(0, counter.get()) // When lifecycle.state = Lifecycle.State.STARTED // Then assertEquals(1, counter.get()) } @Test fun expectOnActiveListenerTriggeredEveryTime() { // Given val lifecycle = TestLifecycle() liveData.observe(lifecycle, Observer { println("$it") }) // verify initial condition assertEquals(0, counter.get()) // When lifecycle.state = Lifecycle.State.STARTED lifecycle.state = Lifecycle.State.CREATED lifecycle.state = Lifecycle.State.STARTED // Then assertEquals(2, counter.get()) } class TestLifecycle : LifecycleOwner { var state: Lifecycle.State = Lifecycle.State.INITIALIZED set(value) { registry.markState(value) } private val lifecycle = object : Lifecycle() { override fun addObserver(observer: LifecycleObserver) { // don't care } override fun removeObserver(observer: LifecycleObserver) { // don't care } override fun getCurrentState(): State = state } private val registry = LifecycleRegistry({ lifecycle }) override fun getLifecycle() = registry } }
Top comments (0)