Pitos
Pitos

Reputation: 867

Type inference failed. MutableMap<Class<out AbsViewModel>, Provider<AbsViewModel>>

kotlin 1.5 changes a type inference warning (present in 1.4) into an error. Is there anyway to ignore the error in 1.5? Currently, I need to downgrade to 1.4 to compile the code.

"Type inference failed. The value of the type parameter K should be mentioned in input types (argument types, receiver type or expected type). Try to specify it explicitly."

--> providerMap[modelClass]

class ViewModelFactory @Inject constructor(private val providerMap: MutableMap<Class<out AbsViewModel>, Provider<AbsViewModel>>) : ViewModelProvider.Factory {
    @Suppress("TYPE_INFERENCE_ONLY_INPUT_TYPES_WARNING", "UNCHECKED_CAST")
    override fun <T : ViewModel> create(modelClass: Class<T>): T {
        (providerMap[modelClass]?.get() as? T)?.let { return it }
        throw Exception("Could not find view model for ${modelClass.canonicalName}")
    }

}

Upvotes: 0

Views: 193

Answers (2)

Tenfour04
Tenfour04

Reputation: 93609

Either make the input type of your Map key Class a wildcard:

class ViewModelFactory @Inject constructor(
    private val providerMap: MutableMap<Class<*>,
            Provider<AbsViewModel>>
) : ViewModelProvider.Factory {
    override fun <T : ViewModel> create(modelClass: Class<T>): T {
        @Suppress("UNCHECKED_CAST")
        (providerMap[modelClass]?.get() as? T)?.let { return it }
        throw Exception("Could not find view model for ${modelClass.canonicalName}")
    }
}

Or if you prefer to enforce the type in the constructor, cast the key:

class ViewModelFactory @Inject constructor(
    private val providerMap: MutableMap<Class<out AbsViewModel>,
            Provider<AbsViewModel>>
) : ViewModelProvider.Factory {
    override fun <T : ViewModel> create(modelClass: Class<T>): T {
        @Suppress("UNCHECKED_CAST")
        (providerMap[modelClass as Class<AbsViewModel>]?.get() as? T)?.let { return it }
        throw Exception("Could not find view model for ${modelClass.canonicalName}")
    }
}

And either way you can simplify your return/throw using ?: instead of ?.let:

return providerMap[modelClass]?.get() as? T 
    ?: error("Could not find view model for ${modelClass.canonicalName}")

Upvotes: 1

rtsketo
rtsketo

Reputation: 1246

class ViewModelFactory @Inject constructor(
    private val providerMap: MutableMap<Class<out AbsViewModel>,
            Provider<AbsViewModel>>) : ViewModelProvider.Factory {

    @Suppress("UNCHECKED_CAST")
    override fun <T : ViewModel> create(modelClass: Class<T>): T {
        (providerMap[modelClass as Class<out AbsViewModel>]?.get() as? T)?.let { return it }
        throw Exception("Could not find view model for ${modelClass.canonicalName}")
    }
}

Upvotes: 1

Related Questions