Last active
April 12, 2021 23:52
-
-
Save fvilarino/0bc71576b593396d9e446eec23b9cf4b to your computer and use it in GitHub Desktop.
Cities MVI ViewModel
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
enum class LoadState { | |
IDLE, | |
LOADING, | |
LOADED, | |
ERROR | |
} | |
data class CityState( | |
val loadState: LoadState, | |
val cities: List<CityResultModel>, | |
val errorMessage: CharSequence, | |
) : State { | |
companion object { | |
val initial = CityState( | |
loadState = LoadState.IDLE, | |
cities = emptyList(), | |
errorMessage = "", | |
) | |
} | |
} | |
sealed class CityMviIntent : MviIntent { | |
data class PrefixUpdated(val prefix: String) : CityMviIntent() | |
} | |
sealed class CityReduceAction : ReduceAction { | |
object Loading : CityReduceAction() | |
data class Loaded(val cities: List<CityResultModel>) : CityReduceAction() | |
data class LoadError(val message: CharSequence) : CityReduceAction() | |
} | |
private const val MIN_CITY_LENGTH_FOR_SEARCH = 3 | |
@HiltViewModel | |
class CityViewModel @Inject constructor( | |
private val getCitiesInteractor: GetCitiesInteractor, | |
private val navigator: Navigator, | |
) : MviViewModel<CityState, CityMviIntent, CityReduceAction>( | |
initialState = CityState.initial | |
) { | |
/* handles Intents from the View */ | |
override suspend fun executeIntent(mviIntent: CityMviIntent) { | |
when (mviIntent) { | |
is CityMviIntent.PrefixUpdated -> { | |
if (mviIntent.prefix.length >= MIN_CITY_LENGTH_FOR_SEARCH) { | |
handle(CityReduceAction.Loading) | |
val result = getCitiesInteractor.execute(mviIntent.prefix) | |
result.fold( | |
onSuccess = { response -> | |
handle( | |
CityReduceAction.Loaded( | |
cities = response.map { city -> city.toCityResultModel() } | |
) | |
) | |
}, | |
onFailure = { | |
handle(CityReduceAction.LoadError("Failed to load cities")) | |
} | |
) | |
} else { | |
handle(CityReduceAction.Loaded(emptyList())) | |
} | |
} | |
} | |
} | |
/* creates a new state as a result of actions distilled from Intents */ | |
override fun reduce(state: CityState, reduceAction: CityReduceAction): CityState = | |
when (reduceAction) { | |
CityReduceAction.Loading -> state.copy( | |
loadState = LoadState.LOADING, | |
errorMessage = "", | |
) | |
is CityReduceAction.Loaded -> state.copy( | |
loadState = LoadState.LOADED, | |
cities = reduceAction.cities, | |
errorMessage = "", | |
) | |
is CityReduceAction.LoadError -> state.copy( | |
loadState = LoadState.ERROR, | |
errorMessage = reduceAction.message, | |
) | |
} | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment