Skip to content

Instantly share code, notes, and snippets.

@gilgoldzweig
Last active January 28, 2019 14:31
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save gilgoldzweig/2e6b267ad00d09fb00df4873f6646ece to your computer and use it in GitHub Desktop.
Save gilgoldzweig/2e6b267ad00d09fb00df4873f6646ece to your computer and use it in GitHub Desktop.
/**
* A base presenter class that include some functionality and helping
*/
abstract class BasePresenter<V : BaseContract.View> :
CoroutineScope, LifecycleObserver, BaseContract.Presenter<V> {
open var job: Job = Job()
var lifecycle: Lifecycle? = null
lateinit var view: V
open var dispatchers: CoroutineDispatchers = CoroutineDispatchers()
override val coroutineContext: CoroutineContext
get() = dispatchers.default + job
val networkContext: CoroutineContext
get() = dispatchers.network + job
val uiContext: CoroutineContext
get() = dispatchers.main + job
val databaseContext: CoroutineContext
get() = dispatchers.database + job
/**
* attach the view to the presenter
* creates a new job if the old one was cancelled
*
* @param view, view to bind
* @param lifecycle a lifecycle we can bind
*/
override fun attach(view: V, lifecycle: Lifecycle?) {
if (job.isCancelled) {
job = Job()
}
this.view = view
if (lifecycle != null) {
bindToLifecycle(lifecycle)
}
}
/**
* Perform an action of the View on the ui context
*
* If a lifecycle is bound then only isAtLeast([Lifecycle.State.STARTED]) and
* we verify that the job is not cancelled
* @see [Lifecycle.getCurrentState]
*/
fun performOnUi(action: V.() -> Unit) {
if (!job.isCancelled &&
lifecycle?.currentState?.isAtLeast(Lifecycle.State.STARTED) != false) {
launch(uiContext) {
view.action()
}
}
}
@CallSuper
fun bindToLifecycle(lifecycle: Lifecycle) {
this.lifecycle = lifecycle
lifecycle.addObserver(this)
}
/**
* Stops all running jobs and remove the lifecycle observer if it exist
*/
@CallSuper
override fun detach() {
job.cancel()
lifecycle?.removeObserver(this)
lifecycle = null
}
@OnLifecycleEvent(Lifecycle.Event.ON_START)
open fun onStart() = Unit
@OnLifecycleEvent(Lifecycle.Event.ON_STOP)
open fun onStop() = Unit
@CallSuper
@OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
open fun onDestroy() {
detach()
}
}
/**
* A way to be able to provide all the dispatchers in a single dependency
* So it is much easier to inject using Dependency injection or just replace
*/
data class CoroutineDispatchers(
val database: CoroutineDispatcher = Dispatchers.IO,
val disk: CoroutineDispatcher = Dispatchers.IO,
val network: CoroutineDispatcher = Dispatchers.IO,
val main: CoroutineDispatcher = Dispatchers.Main,
val default: CoroutineDispatcher = Dispatchers.Default
)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment