miq0717
miq0717

Reputation: 113

Is there any way to handle unchecked cast warning without using Supress in Kotlin?

I am using ViewModelFactory in my android app to pass some data to my ViewModel from Fragment. I'm getting unchecked cast warning. If I'm using Supress the warning goes away. I was wondering is there any way to handle this without using Supress("UNCHECKED_CAST")

The code I'm using to create the ViewModelFactory

val factory: ViewModelProvider.Factory = object : ViewModelProvider.Factory {
        //factory to pass necessary data to ViewModel
        @NonNull
        override fun <T : ViewModel?> create(modelClass: Class<T>): T {
            return activity?.application?.let {
                BookReaderViewModel(
                    it,
                    "local",//todo:remote or local book. value will come from arguments
                    1//todo: bookId will come from arguments
                )
            } as T
        }
    }

as T is getting the warning.

Upvotes: 8

Views: 5642

Answers (1)

RobCo
RobCo

Reputation: 6495

No, an unchecked cast means the compiler cannot guarantee a cast will fail or succeed.

In most cases there is nothing you can add to change that because the compiler simply does not have enough information. This usually happens around generis as T can represent many different types.
You have to add the correct type checks before casting so you are sure the cast succeeds.

You can suppress the warning. By doing that you, as a developer, promise the compiler that you are sure that the cast will always succeed.


The code as it is can't make that promise. If the create function gets called with anything else than a BookReaderViewModel it will crash because the cast doest not succeed.

Here's example where it's safe to suppress the warning because it checks before it casts:

    @NonNull
    @Suppress("UNCHECKED_CAST")
    override fun <T : ViewModel?> create(modelClass: Class<T>): T {
        val application = activity?.application ?: return null
        if (modelClass == BookReaderViewModel::class.java) {
            return BookReaderViewModel(
                application,
                "local",
                1) as T
        }
        // return null or throw exception here
        throw IllegalArguentException("Factory cannot make ViewModel of type ${modelClass.simpleName}")
    }
       

Upvotes: 3

Related Questions