Search code examples
androidkotlinandroid-architecture-componentsandroid-jetpackandroid-viewmodel

how to create view model factory for AndroidViewModel?


I need to pass value when the view model is created (userData), so I need to create a view model factory

here is my viewModel, I need application and userData to init this ScoreViewModel

class ScoreViewModel(application: Application, userData: UserKM) : AndroidViewModel(application) {



}

but now I am confused how to pass application when I create viewModel factory

class ScoreViewModelFactory(private val userData: UserKM) : ViewModelProvider.Factory {

    override fun <T : ViewModel?> create(modelClass: Class<T>): T {
        if (modelClass.isAssignableFrom(ScoreViewModel::class.java)) {

            return ScoreViewModel(userData = userData,application = ?????? ) as T
        }
        throw IllegalArgumentException("Unknown ViewModel class")
    }

}

what should I do ?


Solution

  • You can have something like this :

    class Factory(val app: Application) : ViewModelProvider.Factory {
            override fun <T : ViewModel?> create(modelClass: Class<T>): T {
                if (modelClass.isAssignableFrom(NewsViewModel::class.java)) {
                    @Suppress("UNCHECKED_CAST")
                    return NewsViewModel(app) as T
                }
                throw IllegalArgumentException("Unable to construct viewmodel")
            }
        }
    

    In your activity or fragment you have :

    /**
         * One way to delay creation of the viewModel until an appropriate lifecycle method is to use
         * lazy. This requires that viewModel not be referenced before onActivityCreated, which we
         * do in this Fragment.
         */
        private val viewModel: NewsViewModel by lazy {
            val activity = requireNotNull(this.activity) {
                "You can only access the viewModel after onActivityCreated()"
            }
            ViewModelProviders.of(this, NewsViewModel.Factory(activity.application))
                .get(NewsViewModel::class.java)
        }
    

    And here your viewModel can look like :

    class NewsViewModel(application: Application) : AndroidViewModel(application)
    

    For more detail you can look at : https://github.com/Ali-Rezaei/News-Cache/blob/master/app/src/main/java/com/sample/android/news/viewmodels/NewsViewModel.kt