Android ViewModelProviderFactory in kotlin
Asked Answered
A

1

8

I'm experimenting with the Architecture Components from Google. Specifically I want to implement a ViewModelProvider.Factory to create a ViewModel that takes constructor parameters, like so:

class MyFactory(val handler: Handler) : ViewModelProvider.Factory {
    override fun <T : ViewModel?> create(modelClass: Class<T>?): T {
        return MyViewModel(handler) as T
    }
}

My ViewModel looks like this:

class MyViewModel(val handler: Handler) : ViewModel() 

Anyone knows how to avoid the nasty cast in the end :

return MyViewModel(handler) as T
Antefix answered 4/8, 2017 at 20:6 Comment(3)
you are doing a dangerous working... the client code expect a T extends ViewModel but you give a MyViewModel. when the client code use a specific type of T you always got a ClassCastException, e.g: val model:T = factory.create(T::class.java)Gerstner
That's why I would like to know an alternate approach :)Antefix
you can use reflection to instantiate the ViewModel or use the 3rd IoC container to create the ViewModel.Gerstner
M
13

You could write:

class MyFactory(val handler: Handler) : ViewModelProvider.Factory {
    override fun <T : ViewModel> create(modelClass: Class<T>): T {
        return modelClass.getConstructor(Handler::class.java).newInstance(handler)
    }
}

This will work with any class accepting a Handler as constructor argument and will throw NoSuchMethodException if the class doesn't have the proper constructor.

Modern answered 5/8, 2017 at 2:5 Comment(2)
Since this should be called very rarely, the cost of reflection seems reasonable. Would have hoped for some funky Kotlin goodies, but this will do. Thanks!Antefix
Kotlin goodies like reified generic types are unfortunately not available in this case. Because of type erasure, you can only force cast or use reflection. Also, the default factory already uses reflection to invoke the empty public constructor so the cost would be about the same.Modern

© 2022 - 2024 — McMap. All rights reserved.