DEV Community

Cover image for Implement ViewModelProvider.Factory Interface for Custom ViewModel / AndroidViewModel Factory Creation
Vincent Tsen
Vincent Tsen

Posted on • Edited on • Originally published at vtsen.hashnode.dev

Implement ViewModelProvider.Factory Interface for Custom ViewModel / AndroidViewModel Factory Creation

We do NOT need to extend ViewModelProvider.NewInstanceFactory (for ViewModel) or ViewModelProvider.AndroidViewModel (for AndroidViewModel)

In my previous post - Recommended Ways To Create ViewModel or AndroidViewModel, I mentioned that in order to create ViewModel, we need to create a factory that extends ViewModelProvider.NewInstanceFactory() and to create AndroidViewModel, we need to extend ViewModelProvider.AndroidViewModelFactory().

Well, it works, but it is unnecessary. We can just implement the ViewModelPrvoider.Factory interface directly for both of them.

ViewModelProvider.NewInstanceFactory()

class MyViewModelFactory(private val repository: Repository)
    : ViewModelProvider.NewInstanceFactory() {

    override fun <T : ViewModel?> create(modelClass: Class<T>): T {

        if (modelClass.isAssignableFrom(MyViewModel::class.java)) {
            return MyViewModel(repository) as T
        }

        throw IllegalArgumentException("Unknown ViewModel class")
    }
}
Enter fullscreen mode Exit fullscreen mode

Can be replaced by ViewModelProvider.Factory

class MyViewModelFactory(private val repository: Repository)
    : ViewModelProvider.Factory {

    override fun <T : ViewModel?> create(modelClass: Class<T>): T {

        if (modelClass.isAssignableFrom(MyViewModel::class.java)) {
            return MyViewModel(repository) as T
        }

        throw IllegalArgumentException("Unknown ViewModel class")
    }
}
Enter fullscreen mode Exit fullscreen mode

ViewModelProvider.AndroidViewModelFactory(app)

class MyAndroidViewModelFactory(
    private val app: Application,
    private val repository: Repository)
    : ViewModelProvider.AndroidViewModelFactory(app) {

    override fun <T : ViewModel?> create(modelClass: Class<T>): T {

        if (modelClass.isAssignableFrom(
                MyAndroidViewModel::class.java)) {

            return MyAndroidViewModel(app, repository) as T
        }

        throw IllegalArgumentException("Unknown ViewModel class")
    }
}
Enter fullscreen mode Exit fullscreen mode

Can be replaced by ViewModelProvider.Factory

class MyAndroidViewModelFactory(
    private val app: Application,
    private val repository: Repository)
    : ViewModelProvider.Factory {

    override fun <T : ViewModel?> create(modelClass: Class<T>): T {

        if (modelClass.isAssignableFrom(
                MyAndroidViewModel::class.java)) {

            return MyAndroidViewModel(app, repository) as T
        }

        throw IllegalArgumentException("Unknown ViewModel class")
    }
}
Enter fullscreen mode Exit fullscreen mode

Since both ViewModelProvider.NewInstanceFactory()and ViewModelProvider.AndroidViewModelFactory() implementViewModelPrvoider.Factory interface, we can just implement the ViewModelPrvoider.Factory interface directly to create the custom ViewModel / AndroidViewModel factory which takes in different constructor parameters. We don't need an additional layer here.

Implement_ViewModelProvider_Factory_Interface_01.jpg

By the way, this is the feedback that I get from medium suggesting another better approach is to use Hilt Dependency Injection instead of using factory to create the custom ViewModel, which is also known as constructor dependency injection.

I personally have not used Hilt yet, and will definitely learn and blog about it.

[Updated - July 04, 2022]: I have played around with Hilt a bit and here are the simple steps to implement Hilt into your app.


Originally published at https://vtsen.hashnode.dev.

Top comments (0)