Android75
04/14/2021, 3:03 AMopen class BaseViewModel<State : Any, Event : Any> : ViewModel() {
private val stateLiveData: MutableLiveData<State> = MutableLiveData()
and now with StateFlow:
open class BaseFlowViewModel<State : Any, Event : Any> : ViewModel() {
private val _uiState = MutableStateFlow<State>()
val uiState: StateFlow<State> = _uiState
MutableStateFlow<State>() wants a parameter... what can i put as paramter?Casey Brooks
04/14/2021, 3:09 AMKamilH
04/14/2021, 3:09 AMMutableStateFlow has always value, so it needs initial value, so you need to pass it when initializing. I would suggest to make your BaseViewModel accept initialState, that you will then pass to MutableStateFlow "constructor"Android75
04/14/2021, 3:15 AMprivate val _uiState = MutableStateFlow<State>( Any() as State)Android75
04/14/2021, 3:15 AMCasey Brooks
04/14/2021, 3:18 AMAny to State will crash. You need to create an instance of State with default values that represent “the state of your screen before you’ve started loading or changing anything”.
Typically, I make sure my State class has default values for all its constructor parameters, so that I can simply do MutableStateFlow<State>(State()) in my ViewModel, and leave the “uninitialized-state values” as a concern of the State class itselfAndroid75
04/14/2021, 3:28 AMAndroid75
04/14/2021, 3:28 AMephemient
04/14/2021, 3:32 AMMutableStateFlow<State?>(null) and .filterNotNull() for clientsAndroid75
04/14/2021, 3:33 AMIan Lake
04/14/2021, 3:33 AMMutableSharedFlow, which is a MutableStateFlow without the stateCasey Brooks
04/14/2021, 3:35 AMBaseFlowViewModel a constructor parameter of that initial state. Subclasses must provide the initial value themselves
open class BaseFlowViewModel<State : Any, Events : Any> : ViewModel() {
private val _uiState = MutableStateFlow<State>()
}
class Screen1ViewModel : BaseFlowViewModel<Screen1ViewModel.State, Screen1ViewModel.Events>(Screen1ViewModel.State()) {
data class State(
val loading: Boolean = false,
val intValue: Int = 0,
)
sealed class Events {
object GoToScreen2 : Events()
}
}Android75
04/14/2021, 3:35 AMAndroid75
04/14/2021, 3:37 AMAndroid75
04/14/2021, 4:42 AMAndroid75
04/14/2021, 4:42 AMopen class BaseFlowViewModel<State : Any, Event : Any> : ViewModel() {
val _uiState = MutableStateFlow<State?>(null)
val uiState: StateFlow<State?> = _uiStateAndroid75
04/14/2021, 4:42 AMAndroid75
04/14/2021, 4:43 AMAndroid75
04/14/2021, 4:43 AMabstract class BaseFlowActivityViewBinding<State : Any, Event : Any>() : AppCompatActivity() {Android75
04/14/2021, 4:43 AMlifecycleScope.launchWhenStarted {
provideBaseViewModel().uiState.collect { uiState ->
handleUiState(uiState)
}
}Android75
04/14/2021, 4:44 AMoverride fun handleUiState(state: MainState?) {
when(state){
is MainState.Print ->{
Log.i("asarch", " PRINT")
}
}
}Android75
04/14/2021, 4:48 AMephemient
04/14/2021, 5:42 AMIan Lake
04/14/2021, 6:01 AMstateLiveData.value before that initial value, you'd get nullIan Lake
04/14/2021, 6:03 AMreceiveAsFlow() to process them as per https://elizarov.medium.com/shared-flows-broadcast-channels-899b675e805c#49e3Android75
04/14/2021, 6:24 AMAndroid75
04/14/2021, 7:07 AMJoost Klitsie
04/14/2021, 8:32 AMMutableStatEFlow(ViewState(title = "", items = emptyList())
You can also wrap things in a sealed result object that can be Loading, Success, Error: Result<State>
Then you initialize your state with MutableStateFlow(Loading()) because that is often the state you are in at the beginning, loading your UI.
Also, for event you don't want to use a stateflow. An event is a 1-off thing you fire into the wild, doesn't need to have state (even if it can be replayed).Android75
04/15/2021, 3:11 AMIan Lake
04/15/2021, 3:12 AMStateFlowJoost Klitsie
04/15/2021, 7:09 AM