6

I have a sealed-class like this

sealed class LoadState {
    class Loading : LoadState()
    class Success : LoadState()
    class Fail : LoadState()
}

I use sealed-class with LiveData, it works

open class BaseViewModel: ViewModel() {
//    val loadState by lazy {
//        MutableLiveData<LoadState>()
//    }
    val loadState by lazy {
        MutableStateFlow(LoadState())
    }
}

but when I change MutableLiveData to MutableStateFlow, I get a warning like this

Sealed types cannot be instantiated

so, how to use sealed-class in MutableStateFlow?

General Grievance
  • 4,555
  • 31
  • 31
  • 45
kokod21
  • 61
  • 1
  • 2

4 Answers4

8

You need to specify the type and initial state, like this:

val loadState = MutableStateFlow<LoadState>(LoadState.Loading)
Shwarz Andrei
  • 647
  • 14
  • 17
3

For using MutableStateFlow with sealed class , you can do something like this : Step 1 : Create a sealed class .

sealed class LoadState {
    object Loading : LoadState()
    object Success : LoadState()
    object Fail : LoadState()
}

And then use them in the following way


    private val mutableStateFlow : MutableStateFlow<LoadState?> = MutableStateFlow(null)
    val stateFlow : StateFlow<LoadState?> get() = mutableStateFlow

You can listen to the mutableStateFlow in the following way. In the OnViewCreated of your fragment :

viewLifecycleOwner.lifecycleScope.launch {
            repeatOnLifecycle(Lifecycle.State.STARTED) {

                viewModel.stateFlow.collect { viewState ->
                    when (viewState) {
                       is Loading ->{//do something}

                       is Success ->{//do something}

                       is Fail->{//do something}
                       
                    }
                }
            }
        }

In this way you do not need to specify an initial method everytime . This is how you can use sealed class with mutableState Flow

Karunesh Palekar
  • 2,190
  • 1
  • 9
  • 18
1

Just write your sealed class name as a stateFlow value type, example:

val state = MutableStateFlow<SealedClassName>(SealedClassName.AnySubclassOrObject)
Asilbek
  • 11
  • 2
0

You have to choose your initial state

open class BaseViewModel: ViewModel() {
    val loadState by lazy {
        MutableStateFlow(LoadState.Loading()) <-- for example, initial is loading
    }
}

and also, use data class inside sealed class.

sealed class LoadState {
    data class Loading() : LoadState()
    data class Success() : LoadState()
    data class Fail() : LoadState()
}
Teo
  • 876
  • 9
  • 22
  • If I initial like this , when I write this code ``` loadState.value = LoadState.Fail() ``` I also got a warning ``` Type mismatch. Required: LoadState.Loading Found: LoadState.Fail ``` – kokod21 Aug 19 '21 at 09:55
  • I think u can change the class inside sealed class into `data class`. Maybe can solve your problem – Teo Aug 19 '21 at 09:59
  • 1
    I change to data class, but it doesn't work, I alos got the waring like this `Type mismatch. Required: LoadState.Loading Found: LoadState.Fail ` – kokod21 Aug 19 '21 at 10:08