When working with MutableStateFlow in my viewmodel, I got the following compile error: "Type mismatch. Required: Bar, Found: Unit"
Here is my stripped-down code:
import androidx.lifecycle.ViewModel
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.update
class Bar(
val name : String = "",
val id : Int = 0
)
class TestViewModel : ViewModel() {
private val _testState = MutableStateFlow(Bar())
fun foo() {
_testState.update {
it.copy(name = "fred") // <-- error here
}
}
}
But when I changed Bar to data class Bar
everything compiles just fine. What exactly is going on here? Why does a plain class show up as Unit whereas a data class is correctly interpreted as type Bar?
And lastly, what should I do if I want the functionality of a full class and not a data class (ie inheritance)?
The reason for the mention of Unit in the error: Since a non-data class doesn’t have a copy()
function, the compiler doesn’t know what the return type of this supposed copy()
function should be, so it’s apparently using Unit as a default inferred return type. This cascades up to a secondary error about your update
lambda returning the wrong type. Basically, one error triggers another error, leading to a confusing error message.
If you want Bar to be an open class
instead of a data class
you will have to manually create your own copy()
function if you need one, but beware that the definition of what a copy is becomes ambiguous when there are subclasses. Probably the main reason it is forbidden to subclass a data class.
Note that it is fine for data classes to be subclasses of other types or interfaces. They just can’t have subclasses of their own.