androidkotlinmutablestateflow

android kotlin `when` statement not smart casting


I have the following state sealed interface

sealed interface MainState {
    data class Success(
        val hasUsername: Boolean = false,
        val isSessionActive: Boolean = false) : MainState

    data object Loading : MainState
}

and my MainViewModel

 private val _mainState = MutableStateFlow(MainState.Loading)
    val mainState = _mainState.asStateFlow()
        .onStart {
            if(!hasCompleted) {
                getLoginCredentials()
                hasCompleted = true
            }

then in my composable

 val mainState by mainViewModel.mainState.collectAsStateWithLifecycle(initialValue = MainState.Loading)
       
        when(val status = mainState) {
           MainState.Loading -> {
                Box(
                    modifier = Modifier.fillMaxSize(),
                    contentAlignment = Alignment.Center
                ) {
                    CircularProgressIndicator()
                }
            }
            is MainState.Success -> {
                NavHost(
                    navController = navController,
                    startDestination = if(status.isSessionActive) Route.DashboardGraph else Route.AuthenticationGraph
                ) {

                    this.authentication(navController)

                    this.dashboardGraph(navController)

                    this.settingsGraph(navController)
                }
            }
        }
            }

And I am getting the following error at this line is MainState.Success -> {

This is the error Incompatible types: MainState. Success and MainState. Loading


Solution

  • Try replacing:

    private val _mainState = MutableStateFlow(MainState.Loading)
    

    with:

    private val _mainState: MutableStateFlow<MainState> = MutableStateFlow(MainState.Loading)
    

    or:

    private val _mainState = MutableStateFlow<MainState>(MainState.Loading)
    

    Kotlin's type inference is cool but not magic. In your original formulation, it inferred that the type was MutableStateFlow<MainState.Loading>. Since MainState.Success is not a subtype of MainState.Loading, your is MainState.Success branch was deemed to be impossible. We have to teach the compiler that you really wanted the supertype, despite initializing it to the subtype.