Pferdesalbe
Pferdesalbe

Reputation: 213

state based shown screen - jetpack compose

I wanted to show a special screen based on the state the stateholder provides. When the application is starting, a api has to be called. Since this can take a while a loadin screen should be shown. Is the request success, then show a success screen, otherwise a screen with an error message.

sealed interface ScreenLoadingState {
    data object Loading : ScreenLoadingState
    data class Success(val data: String) : ScreenLoadingState
    data class Failed(val errorMessage: String) : ScreenLoadingState
}

data class AlbumScreenState(
    val selectedUser: User,
    val albumList: List<Album>,
    val screenLoadingState: ScreenLoadingState = ScreenLoadingState.Loading
)

class AlbumScreenViewModel : ViewModel() {
    private val _uiState: MutableStateFlow<AlbumScreenState> = MutableStateFlow(
        AlbumScreenState(
            selectedUser = User() // from other screen
            albumList = emptyList()
        )
    )
    val uiState: StateFlow<AlbumScreenState> = _uiState.asStateFlow()
}

@Composable
fun AlbumScreen(
    albumScreenViewModel: AlbumScreenViewModel
) {
    val albumScreenState by albumScreenViewModel.uiState.collectAsState()

    when(albumScreenState.screenLoadingState) {
        is ScreenLoadingState.Loading -> {}
        is ScreenLoadingState.Success -> {}
        is ScreenLoadingState.Failed -> {
            val a = albumScreenState.screenLoadingState.errorMessage
        }
    }

}

The when expression in shows an error, "Smart cast to 'ScreenLoadingState.Failed' is impossible, because 'albumScreenState.screenLoadingState' is a complex expression"

Why is this not possible? The when expression checks every possible state. There are just this three options. If it is an Error, then it holds the errormessage, so why does this error appear and how to avoid such a problem?

By the way is this consruct with sealed interface, data class an viewmodel correct or is there a better solution?

Thanks for help :-D

Upvotes: 1

Views: 192

Answers (1)

Waseem Abbas
Waseem Abbas

Reputation: 865

You're defining the state nicely with the sealed interface and data class. Sometimes the compiler is unable to smart cast because of the delegate keyword by. Try introducing a when-expression scoped variable to represent the state.

@Composable
fun AlbumScreen(
    albumScreenViewModel: AlbumScreenViewModel
) {
    val albumScreenState by albumScreenViewModel.uiState.collectAsState()

    when(val state = albumScreenState.screenLoadingState) {
        is ScreenLoadingState.Loading -> {}
        is ScreenLoadingState.Success -> {}
        is ScreenLoadingState.Failed -> {
            val a = state.errorMessage
        }
    }

}

Happy coding

Upvotes: 2

Related Questions