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

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)

ยท

2 min read

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")
    }
}

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")
    }
}

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")
    }
}

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")
    }
}

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.

Did you find this article valuable?

Support Vincent Tsen - AndroidDev Blog by becoming a sponsor. Any amount is appreciated!

ย