Home > Enterprise >  Why can't I get data directly from a sealed class in Kotlin?
Why can't I get data directly from a sealed class in Kotlin?

Time:03-30

I hope to get data from a sealed class Result<out R>, but val mydata = queryList.data cause the following error, how can I fix it?

Error Information Smart cast to 'Result.Success<Flow<List>>' is impossible, because 'queryList' is a property that has open or custom getter

@Composable
fun Greeting(
    name: String   
) {
     Column( ) {
        val queryList by produceState(initialValue = aa() ) {
            value = mViewMode.listRecord()
        }

        when (queryList) {
            is Result.Error -> {}
            is Result.Loading -> {}
            is Result.Success -> {
                val mydata = queryList.data //It cause error
            }
        }
    }
}


sealed class Result<out R> {
    data class Success<out T>(val data: T) : Result<T>()
    data class Error(val exception: Exception) : Result<Nothing>()
    object Loading : Result<Nothing>()
}


fun aa(): Result<Flow<List<MRecord>>> {
    return Result.Loading
}

CodePudding user response:

Cache the returned property value in a local variable so it can be smart cast. It can’t be smart cast without a local variable because it’s a delegated property.

You can do it right in the when statement:

when (val result = queryList) {
    is Result.Error -> {}
    is Result.Loading -> {}
    is Result.Success -> {
        val mydata = result.data
        // ..
    }
}

CodePudding user response:

As stated in the error text, Kotlin cannot be sure that the next call to your delegated property queryList has the same type as the last one, and hence the variable cannot be smart cast. This can be solved by casting your variable explicitly:

when (queryList) {
    is Result.Error -> {}
    is Result.Loading -> {}
    is Result.Success -> {
        val mydata = (queryList as Result.Success).data
    }
}

If your property delegate does in fact create a new element each time you call queryList, it is advisable to store the value you are checking in a new variable like this:

val q = queryList
when (q) {
    is Result.Error -> {}
    is Result.Loading -> {}
    is Result.Success -> {
        val mydata = q.data
    }
}

Note that in this case Kotlin is able to smart cast q.data because q is just a simple read-only variable.

  • Related