Skip to content

Instantly share code, notes, and snippets.

@premacck
Last active May 15, 2020 07:58
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 premacck/b864b936f8ec6cde868b5c7eb24afe5a to your computer and use it in GitHub Desktop.
Save premacck/b864b936f8ec6cde868b5c7eb24afe5a to your computer and use it in GitHub Desktop.
StateAwareEpoxyController for state aware loading of views in RecyclerViews using Epoxy library by AirBnb (https://github.com/airbnb/epoxy)
const val STATE_LOADING = 0
const val STATE_SUCCESS = 1
const val STATE_EMPTY = 2
const val STATE_ERROR = 3
@Retention @IntDef(STATE_LOADING, STATE_SUCCESS, STATE_EMPTY, STATE_ERROR) annotation class LoadState
import com.airbnb.epoxy.EpoxyController
import com.airbnb.epoxy.Typed2EpoxyController
import com.doi.garasi.base.constants.*
/**
* Prem's creation, on 09/05/20
*
* Common class for all the [EpoxyController]s that have a [List] and want to be state aware,
* to handle [STATE_LOADING], [STATE_SUCCESS], [STATE_EMPTY], and [STATE_ERROR] states of data
*/
abstract class StateAwareEpoxyController<DATA_TYPE>(private val isSameStateForErrorAndEmpty: Boolean = false) : Typed2EpoxyController<DATA_TYPE, Int>() {
/**
* Optional convenient override for the child controllers to get the data in respective callback functions directly,
* without having to implement the when case themselves
*
* This is useful in case the child controller doesn't customise the way the states are implemented here.
*
* Note: to remove the unnecessary different name warning in the sub-classes, you can:
* - Go to Preferences -> Editor -> Inspections and type "Parameter name differs from" in the search box
* - Select the Severity to "No highlighting", only fix in All Scope
*/
override fun buildModels(data: DATA_TYPE?, @LoadState loadState: Int) {
onPreLoadState(data, loadState)
when (loadState) {
STATE_LOADING -> onLoadingState()
STATE_SUCCESS -> onSuccessState(data)
STATE_EMPTY -> if (isSameStateForErrorAndEmpty) onErrorOrEmptyState(data) else onEmptyState()
STATE_ERROR -> if (isSameStateForErrorAndEmpty) onErrorOrEmptyState(data) else onErrorState()
}
onPostLoadState(data, loadState)
}
/**
* Convenient function to add anything to the controller BEFORE the State aware components are added
*
* Works only if [buildModels] of this class is called
*/
protected open fun onPreLoadState(data: DATA_TYPE?, @LoadState loadState: Int) {}
/**
* Convenient function to add anything to the controller AFTER the State aware components are added
*
* Works only if [buildModels] of this class is called
*/
protected open fun onPostLoadState(data: DATA_TYPE?, @LoadState loadState: Int) {}
/** Optional callback for [STATE_LOADING] state */
protected open fun onLoadingState() {}
/** Optional callback for [STATE_SUCCESS] state */
protected open fun onSuccessState(data: DATA_TYPE?) {}
/** Optional callback for [STATE_EMPTY] state. Not called when [isSameStateForErrorAndEmpty] is true */
protected open fun onEmptyState() {}
/** Optional callback for [STATE_ERROR] state. Not called when [isSameStateForErrorAndEmpty] is true */
protected open fun onErrorState() {}
/** Optional callback for [STATE_EMPTY] or [STATE_ERROR] state. This is called only when [isSameStateForErrorAndEmpty] is true */
protected open fun onErrorOrEmptyState(data: DATA_TYPE?) {}
/**
* Open Function to set the data in [StateAwareEpoxyController] without having to pass in the [LoadState]
* If the object or List is null, [LoadState] will be [STATE_ERROR]
* If the object is a list and the List is empty, the [LoadState] will be [STATE_EMPTY]
* If the object or List is not null or empty, [LoadState] will be [STATE_SUCCESS]
*/
open fun setData(data: DATA_TYPE?) = setData(
data, when (data) {
null -> STATE_ERROR
is Collection<*> -> when {
data.isEmpty() -> STATE_EMPTY
else -> STATE_SUCCESS
}
else -> STATE_SUCCESS
}
)
/**
* Function to set [STATE_LOADING] in a [StateAwareEpoxyController]
*/
protected fun setLoadingState() {
cancelPendingModelBuild()
setData(null, STATE_LOADING)
}
}
/**
* Class for implementing simple list controllers
*/
abstract class StateAwareEpoxyControllerList<CLASS_OF_LIST>(sameErrorAndEmptyStates: Boolean = false) : StateAwareEpoxyController<List<CLASS_OF_LIST>>(sameErrorAndEmptyStates)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment