DEV Community

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

Posted on • Updated 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)

This article was originally published at vtsen.hashnode.dev on Oct 30, 2021.

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.

Discussion (0)