Last active
December 6, 2022 14:32
-
-
Save vishalratna-microsoft/29595b266bd48a31ab2e06a325853d68 to your computer and use it in GitHub Desktop.
ViewBased implementation of LazyLifecycleManager
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
import android.util.Log | |
import android.view.ViewTreeObserver | |
import androidx.lifecycle.Lifecycle | |
import androidx.lifecycle.LifecycleOwner | |
import ************.Barrier | |
import javax.inject.Inject | |
/** | |
* ViewBasedLazyLifecycleManager is small construct to ensure that we initialise not so necessary | |
* things required in onCreate()/onStart()/onResume() lazily. By default it watches on the number of draws | |
* on decor view or has an SLA of 4 seconds. | |
* While one execution is in flight, this construct prevents the subsequent calls to lazy methods. | |
* Implementor should implement [LazyLifecycleCallbacks] and override its methods. | |
* And [ViewBasedLazyLifecycleManager.activate] should be called in onResume(). | |
*/ | |
// Currently built for activities. Will do it for fragment once this is successful. | |
///////////////////////////////////////////////////////////// | |
// NOTE: Should always be a activity scoped singleton. ///// | |
/////////////////////////////////////////////////////////// | |
class ViewBasedLazyLifecycleManager(owner: LifecycleOwner, private val drawsToWait: Int, private val sla: Long) : LazyLifecycleManager(owner) { | |
private var state: State = State.Rest // Init with resting state | |
override fun setupLifecycleTrigger(owner: LifecycleOwner) { | |
if (state == State.Active) { | |
Log.d(TAG, "Execution is in flight already bailing out!") | |
return | |
} | |
val onPreDrawListener: ViewTreeObserver.OnPreDrawListener = object : ViewTreeObserver.OnPreDrawListener { | |
val lazyBarrier = Barrier.with(getCondition(owner, drawsToWait)) | |
.withSLA(sla, true) | |
.runOnBreak { | |
val copyReference = this | |
with(owner as LazyLifecycleCallbacks) { | |
watchedView.viewTreeObserver.removeOnPreDrawListener(copyReference) | |
triggerLazyLifecycleCallbacks() | |
} | |
// Move to the next state. | |
state = state.next().also { Log.d(TAG, "Incrementing lazy lifecycle trigger state") } | |
}.startSLA() | |
override fun onPreDraw(): Boolean { | |
lazyBarrier.strike() | |
return true | |
} | |
} | |
(owner as LazyLifecycleCallbacks).watchedView.viewTreeObserver.addOnPreDrawListener(onPreDrawListener) | |
// Move to next state. | |
state = state.next() | |
} | |
private fun getCondition(owner: LifecycleOwner, drawsToWait: Int): Barrier.Condition { | |
return object : Barrier.Condition { | |
var drawCount = 1 | |
val finalDrawsToWait = drawsToWait | |
override fun evaluate(): Boolean { | |
return if (owner.lifecycle.currentState.isAtLeast(Lifecycle.State.RESUMED)) { | |
if (drawCount == finalDrawsToWait) { | |
true | |
} else { | |
if (drawCount > finalDrawsToWait) { | |
return true | |
} | |
drawCount++ | |
false | |
} | |
} else false | |
} | |
} | |
} | |
companion object { | |
const val TAG = "ViewBasedLazyLifecycleCallbacks" | |
} | |
} | |
// Represents the state of the lifecycle callback trigger. | |
private enum class State { | |
Rest { | |
override fun next(): State = Active | |
}, | |
Active { | |
override fun next(): State = Rest | |
}; | |
abstract fun next(): State | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment