Last active
June 28, 2022 07:27
-
-
Save vishalratna-microsoft/22b601ee7b78c02922dbd3dbb9e58111 to your computer and use it in GitHub Desktop.
Code for LazyLifecycleManager base class
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.app.Activity | |
import android.os.Handler | |
import android.os.Looper | |
import androidx.annotation.MainThread | |
import androidx.lifecycle.Lifecycle | |
import androidx.lifecycle.LifecycleOwner | |
import *******.Closure | |
import *******.Once | |
import *******.LazyLifecycleManagerType.ViewBased | |
import java.lang.ref.WeakReference | |
/** | |
* Lazy lifecycle implementations could wait for draws, scenarios or some other events. Each of them | |
* or their combinations can represent a trigger. | |
* This is the general contract that needs to be adhered by all the managers. | |
*/ | |
abstract class LazyLifecycleManager(owner: LifecycleOwner) { | |
protected val lifecycleOwner: WeakReference<LifecycleOwner> = WeakReference(owner) | |
private val executeLazyCreateOnce = Once() | |
/** | |
* When activate() is called, it installs a barrier at the point that guards the target code. | |
* This method is meant for lazy initialisations or calls that could be deferred. | |
* This is not meant for calls that are purely dependent on activity lifecycle transitions eg. | |
* registering broadcast receivers in onStart() and unregistering them in onStop(). These type | |
* of complimentary calls should NOT be added in lazy callbacks as we do not provide lazy versions of | |
* onPause() and onStop() and it is not needed too. It is always good to depend on android in these cases. | |
*/ | |
@MainThread | |
fun activate() { | |
if (checkIfContractsValid()) { | |
lifecycleOwner.get()?.let { | |
setupLifecycleTrigger(it) | |
} | |
} | |
} | |
/** | |
* Implementation should add the actual code to fire the lazy lifecycle callbacks in this method. | |
* Default implementation of what happens after trigger is provided in [triggerLazyLifecycleCallbacks] | |
*/ | |
abstract fun setupLifecycleTrigger(owner: LifecycleOwner) | |
/** | |
* If required, deactivates the lazy lifecycle callbacks. Can be used for cleanup of held objects too. | |
* Default implementation is a noop. | |
*/ | |
open fun deactivate() {} | |
protected fun triggerLazyLifecycleCallbacks() { | |
this.lifecycleOwner.get()?.let { owner -> | |
if (owner.isVisible()) { | |
// Execute onLazyOnCreate() only once per instance. | |
with((owner as LazyLifecycleCallbacks)) { | |
executeLazyCreateOnce.run(object : Closure { | |
override fun invoke() { | |
// We use post instead of direct execution. executing directly might cause main thread to freeze. | |
uiHandler.post { | |
if (owner.isVisible()) { | |
onLazyCreate() | |
} else executeLazyCreateOnce.reset() | |
} | |
} | |
}) | |
uiHandler.post { | |
if (owner.isVisible()) { | |
onLazyStart() | |
} | |
} | |
uiHandler.post { | |
if (owner.isVisible()) { | |
onLazyResume() | |
} | |
} | |
} | |
} | |
} | |
} | |
private fun checkIfContractsValid(): Boolean { | |
lifecycleOwner.get()?.let { owner -> | |
if (owner !is LazyLifecycleCallbacks || owner !is Activity) { | |
throw ClassCastException( | |
"Not able to cast LifeCycleOwner to LazyLifecycleCallbacks. " + | |
"Please implement LazyLifecycleCallbacks interface before calling activate()" | |
) | |
} | |
// Returns false, if the implementation does not support lazy lifecycle callbacks. | |
if (owner.supportsLazyLifecycleCallbacks().not()) { | |
return false | |
} | |
return true | |
} | |
return false | |
} | |
protected fun LifecycleOwner.isVisible(): Boolean = lifecycle.currentState.isAtLeast(Lifecycle.State.RESUMED) | |
companion object { | |
private val uiHandler = Handler(Looper.getMainLooper()) | |
} | |
} | |
// Add any new type of lifecycle manager here. | |
sealed class LazyLifecycleManagerType { | |
data class ViewBased @JvmOverloads constructor(val drawsCount: Int = 5, val timeout: Long = 6000) : LazyLifecycleManagerType() | |
// Add another implementations here | |
} | |
class LazyLifecycleManagerFactory constructor() { | |
private lateinit var lazyLifecycleCallbackManager: LazyLifecycleManager | |
@MainThread | |
fun get(owner: LifecycleOwner, type: LazyLifecycleManagerType): LazyLifecycleManager { | |
if (::lazyLifecycleCallbackManager.isInitialized.not()) { | |
lazyLifecycleCallbackManager = when (type) { | |
is ViewBased -> ViewBasedLazyLifecycleManager(owner, type.drawsCount, type.timeout) | |
} | |
} | |
return lazyLifecycleCallbackManager | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment