Created
July 14, 2021 10:44
-
-
Save mattmook/ea9805da5972732d37eff042f308f97e to your computer and use it in GitHub Desktop.
The state of MVI on Android - Roxie - NoteListViewModel
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
class NoteListViewModel( | |
initialState: State?, | |
private val loadNoteListUseCase: GetNoteListUseCase | |
) : CoroutineViewModel<Action, State>() { | |
override val initialState = initialState ?: State(isIdle = true) | |
private val reducer: Reducer<State, Change> = { state, change -> | |
when (change) { | |
is Change.Loading -> state.copy( | |
isIdle = false, | |
isLoading = true, | |
notes = emptyList(), | |
isError = false | |
) | |
is Change.Notes -> state.copy( | |
isLoading = false, | |
notes = change.notes | |
) | |
is Change.Error -> state.copy( | |
isLoading = false, | |
isError = true | |
) | |
} | |
} | |
init { | |
bindActions() | |
} | |
private fun bindActions() { | |
val loadNotesChange: Flow<Change> = actions.asFlow() | |
.ofType<Action.LoadNotes>() | |
.flatMapLatest { | |
loadNoteListUseCase.loadAll() | |
.flowOn(Dispatchers.IO) | |
.map { Change.Notes(it) } | |
.defaultOnEmpty(Change.Notes(emptyList())) | |
.catch<Change> { | |
emit(Change.Error(it)) | |
} | |
.onStart { emit(Change.Loading) } | |
} | |
// to handle multiple Changes, use Observable.merge to merge them into a single stream: | |
// val allChanges = Observable.merge(loadNotesChange, ...) | |
loadNotesChange | |
.scan(initialState) { state, change -> | |
reducer.invoke(state, change) | |
} | |
.filter { !it.isIdle } | |
.distinctUntilChanged() | |
.flowOn(Dispatchers.Main) | |
.observeState() | |
.catch { | |
Timber.e(it) | |
} | |
.launchHere() | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment