Skip to content

Instantly share code, notes, and snippets.

@MaxMichel2
Last active June 20, 2024 11:58
Show Gist options
  • Save MaxMichel2/870c6b05aa9650b139ca29ec04ec0758 to your computer and use it in GitHub Desktop.
Save MaxMichel2/870c6b05aa9650b139ca29ec04ec0758 to your computer and use it in GitHub Desktop.
The abstract class defining the MVI ViewModel that is inherited by all ViewModels
abstract class BaseViewModel<State : Reducer.ViewState, Event : Reducer.ViewEvent, Effect : Reducer.ViewEffect>(
initialState: State,
private val reducer: Reducer<State, Event, Effect>
) : ViewModel() {
private val _state: MutableStateFlow<State> = MutableStateFlow(initialState)
val state: StateFlow<State>
get() = _state.asStateFlow()
private val _event: MutableSharedFlow<Event> = MutableSharedFlow()
val event: SharedFlow<Event>
get() = _event.asSharedFlow()
private val _effects = Channel<Effect>(capacity = Channel.CONFLATED)
val effect = _effects.receiveAsFlow()
val timeCapsule: TimeCapsule<State> = TimeTravelCapsule { storedState ->
_state.tryEmit(storedState)
}
init {
timeCapsule.addState(initialState)
}
fun sendEffect(effect: Effect) {
_effects.trySend(effect)
}
fun sendEvent(event: Event) {
val (newState, _) = reducer.reduce(_state.value, event)
val success = _state.tryEmit(newState)
if (success) {
timeCapsule.addState(newState)
}
}
fun sendEventForEffect(event: Event) {
val (newState, effect) = reducer.reduce(_state.value, event)
val success = _state.tryEmit(newState)
if (success) {
timeCapsule.addState(newState)
}
effect?.let {
sendEffect(it)
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment