The Code A is from offical sample code here.
I think I can pass _uiState
to uiState
directly, so I write Code B, it seems that Code B can work well.
Can I pass a MutableStateFlow
object to a StateFlow
variable directly?
Code A
class InterestsViewModel(
private val interestsRepository: InterestsRepository
) : ViewModel() {
// UI state exposed to the UI
private val _uiState = MutableStateFlow(InterestsUiState(loading = true))
val uiState: StateFlow<InterestsUiState> = _uiState.asStateFlow()
...
}
Code B
class InterestsViewModel(
private val interestsRepository: InterestsRepository
) : ViewModel() {
// UI state exposed to the UI
private val _uiState = MutableStateFlow(InterestsUiState(loading = true))
val uiState: StateFlow<InterestsUiState> = _uiState
...
}
CodePudding user response:
Yes, this is fine. There is one small functional advantage to asStateFlow()
. It does not simply upcast to a read-only StateFlow, but also wraps it in a read-only StateFlow, such that a receiver cannot cast it to a MutableStateFlow and use its publishing functions. However, this should be considered something that no reasonable code should ever do, because it is asking for trouble to forcibly mutate something that is declared as read-only.
There is no equivalent asList()
for MutableList()
, so I'm not sure why they felt Flows need this feature and Collections don't. I can't find any discussion of it. It appeared in the same commit that first introduced StateFlow and SharedFlow.
A secondary feature of asStateFlow()
is that it permits writing this kind of code more concisely.
val uiState = _uiState.asStateFlow()
is easier and faster to write than
val uiState: StateFlow<InterestsUiState> = _uiState
or
val uiState = _uiState as StateFlow<InterestsUiState>
especially if the type is long or complicated, such as StateFlow<List<SomeApi.Subtype>>
, for example.