Last active
May 15, 2020 07:58
-
-
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)
This file contains hidden or 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
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 |
This file contains hidden or 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 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