How to add additional parameters to ViewModel via Kotlin

With the new android.arch.lifecycle.ViewModel, you can extend your own ViewModel which is life cycle aware. Or you can use AndroidViewModel if you want to inject context to your model. One problem with the default ViewModel is the constructor takes zero parameters. If you want to make it takes parameters, you need to make a new FactoryClass for each view model. But with Kotlin, it could be more simple. Let’s see how to do it.

1. Normal way

If you want your view model to have a constructor which takes a parameter like this

1
2
3
class MyViewModel(
val name:String
):ViewModel() {}

You need to create an according factory class like this:

1
2
3
4
5
6
7
class MyViewModelFactory(
private val name: String
): ViewModelProvider.NewInstanceFactory() {
override fun <T: ViewModel> create(modelClass:Class<T>): T {
return MyViewModel(name) as T
}
}

And use it:

1
2
3
4
binding.authViewModel = ViewModelProviders.of(
this,
MyViewModelFactory("albert")
).get(MyViewModel::class.java)

2. Kotlin way

The previous way works, but you have to create many factory class like that which seems overkill. So a more elegant kotlin is like this:

1
2
3
4
protected inline fun <VM : ViewModel> viewModelFactory(crossinline f: () -> VM) =
object : ViewModelProvider.Factory {
override fun <T : ViewModel> create(aClass: Class<T>):T = f() as T
}

And use it like this:

1
2
3
4
binding.authViewModel = ViewModelProviders.of(
this,
viewModelFactory { MyViewModel("albert") }
).get(AuthViewModel::class.java)

You can add that viewModelFactory to your BaseActivity class so you can use it across apps.

3. End

Hope it helps.

Thanks for reading!

Follow me (albertgao) on twitter, if you want to hear more about my interesting ideas.