generated from bitwarden/template
-
Notifications
You must be signed in to change notification settings - Fork 28
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
BIT-145: Add BaseViewModel and update existing ViewModels (#11)
- Loading branch information
1 parent
ee199b9
commit 2ff4912
Showing
4 changed files
with
90 additions
and
12 deletions.
There are no files selected for viewing
79 changes: 79 additions & 0 deletions
79
app/src/main/java/com/x8bit/bitwarden/ui/base/BaseViewModel.kt
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
package com.x8bit.bitwarden.ui.base | ||
|
||
import androidx.lifecycle.ViewModel | ||
import androidx.lifecycle.viewModelScope | ||
import kotlinx.coroutines.channels.Channel | ||
import kotlinx.coroutines.channels.SendChannel | ||
import kotlinx.coroutines.flow.Flow | ||
import kotlinx.coroutines.flow.MutableStateFlow | ||
import kotlinx.coroutines.flow.StateFlow | ||
import kotlinx.coroutines.flow.asStateFlow | ||
import kotlinx.coroutines.flow.consumeAsFlow | ||
import kotlinx.coroutines.flow.receiveAsFlow | ||
import kotlinx.coroutines.launch | ||
|
||
/** | ||
* A base [ViewModel] that helps enforce the unidirectional data flow pattern and associated | ||
* responsibilities of a typical ViewModel: | ||
* | ||
* - Maintaining and emitting a current state (of type [S]) with the given `initialState`. | ||
* - Emitting one-shot events as needed (of type [E]). These should be rare and are typically | ||
* reserved for things such as non-state based navigation. | ||
* - Receiving actions (of type [A]) that may induce changes in the current state, trigger an | ||
* event emission, or both. | ||
*/ | ||
abstract class BaseViewModel<S, E, A>( | ||
initialState: S, | ||
) : ViewModel() { | ||
protected val mutableStateFlow: MutableStateFlow<S> = MutableStateFlow(initialState) | ||
protected val eventChannel: Channel<E> = Channel(capacity = Channel.UNLIMITED) | ||
private val internalActionChannel: Channel<A> = Channel(capacity = Channel.UNLIMITED) | ||
|
||
/** | ||
* A [StateFlow] representing state updates. | ||
*/ | ||
val stateFlow: StateFlow<S> = mutableStateFlow.asStateFlow() | ||
|
||
/** | ||
* A [Flow] of one-shot events. These may be received and consumed by only a single consumer. | ||
* Any additional consumers will receive no events. | ||
*/ | ||
val eventFlow: Flow<E> = eventChannel.receiveAsFlow() | ||
|
||
/** | ||
* A [SendChannel] for sending actions to the ViewModel for processing. | ||
*/ | ||
val actionChannel: SendChannel<A> = internalActionChannel | ||
|
||
init { | ||
viewModelScope.launch { | ||
internalActionChannel | ||
.consumeAsFlow() | ||
.collect { action -> | ||
handleAction(action) | ||
} | ||
} | ||
} | ||
|
||
/** | ||
* Handles the given [action] in a synchronous manner. | ||
* | ||
* Any changes to internal state that first require asynchronous work should post a follow-up | ||
* action that may be used to then update the state synchronously. | ||
*/ | ||
protected abstract fun handleAction(action: A): Unit | ||
|
||
/** | ||
* Helper method for sending an internal action. | ||
*/ | ||
protected suspend fun sendAction(action: A) { | ||
actionChannel.send(action) | ||
} | ||
|
||
/** | ||
* Helper method for sending an event. | ||
*/ | ||
protected fun sendEvent(event: E) { | ||
viewModelScope.launch { eventChannel.send(event) } | ||
} | ||
} |
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
17 changes: 8 additions & 9 deletions
17
app/src/main/java/com/x8bit/bitwarden/ui/feature/rootnav/RootNavViewModel.kt
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
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