Impossible de créer une instance de la classe ViewModel dans le nouveau projet

Nov 25 2020

J'ai deux projets différents. Dans le premier, j'utilise ViewModel avec mon activité et la base de données de la salle. Tout fonctionne. Ensuite, je viens de créer un nouveau projet à des fins différentes et là, j'instancie ViewModel de la même manière, mais mon application plante avec cette erreur:

java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example/com.example.MainActivity}: java.lang.RuntimeException: Cannot create an instance of class com.example.MainViewModel
    at android.app.ActivityThread.performLaunchActivity(Unknown Source:591)
    at android.app.ActivityThread.handleLaunchActivity(Unknown Source:36)
    at android.app.servertransaction.LaunchActivityItem.execute(Unknown Source:57)
    at android.app.servertransaction.TransactionExecutor.executeCallbacks(Unknown Source:99)
    at android.app.servertransaction.TransactionExecutor.execute(Unknown Source:34)
    at android.app.ActivityThread$H.handleMessage(Unknown Source:36) at android.os.Handler.dispatchMessage(Unknown Source:21) at android.os.Looper.loop(Unknown Source:207) at android.app.ActivityThread.main(Unknown Source:107) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(Unknown Source:11)
    at com.android.internal.os.ZygoteInit.main(Unknown Source:274)
 Caused by: java.lang.RuntimeException: Cannot create an instance of class com.example.MainViewModel
    at androidx.lifecycle.ViewModelProvider$NewInstanceFactory.create(ViewModelProvider.java:221) at androidx.lifecycle.ViewModelProvider.get(ViewModelProvider.java:187) at androidx.lifecycle.ViewModelProvider.get(ViewModelProvider.java:150) at com.kazguiu.MainActivity.applyAdapterAndViewModel(MainActivity.kt:37) at com.kazguiu.MainActivity.onCreate(MainActivity.kt:25) at android.app.Activity.performCreate(Unknown Source:16) at android.app.Activity.performCreate(Unknown Source:1) at android.app.Instrumentation.callActivityOnCreate(Unknown Source:3) at android.app.ActivityThread.performLaunchActivity(Unknown Source:368) at android.app.ActivityThread.handleLaunchActivity(Unknown Source:36)  at android.app.servertransaction.LaunchActivityItem.execute(Unknown Source:57)  at android.app.servertransaction.TransactionExecutor.executeCallbacks(Unknown Source:99)  at android.app.servertransaction.TransactionExecutor.execute(Unknown Source:34)  at android.app.ActivityThread$H.handleMessage(Unknown Source:36) 
    at android.os.Handler.dispatchMessage(Unknown Source:21) 
    at android.os.Looper.loop(Unknown Source:207) 
    at android.app.ActivityThread.main(Unknown Source:107) 
    at java.lang.reflect.Method.invoke(Native Method) 
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(Unknown Source:11)  at com.android.internal.os.ZygoteInit.main(Unknown Source:274)  Caused by: java.lang.InstantiationException: java.lang.Class<com.example.MainViewModel> has no zero argument constructor at java.lang.Class.newInstance(Native Method) at androidx.lifecycle.ViewModelProvider$NewInstanceFactory.create(ViewModelProvider.java:219)

J'instancie ViewModel en activité comme ceci:

private lateinit var mainViewModel: MainViewModel

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)

    applyAdapterAndViewModel()

}

private fun applyAdapterAndViewModel() {
    mainViewModel = ViewModelProvider(this).get(MainViewModel::class.java)
}

Mon ViewModel:

class MainViewModel(application: Application) : AndroidViewModel(application) {

    private val exampleDao = Database.getDatabase(application).exampleDao()
    private val repository = Repository(exampleDao)

    fun getSubjects() = repository.getSubjects()

    fun addSubjects(subject: Subjects) = viewModelScope.launch(Dispatchers.IO) {
        repository.addSubject(subject)
    }

}

Cette façon d'utiliser ViewModel est la même que mon projet précédent. La seule différence est que j'ai deux dépendances supplémentaires dans mon grade actuel:

implementation 'androidx.lifecycle:lifecycle-livedata-ktx:2.2.0'
implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.2.0'

Si je les supprime, Android Studio ne reconnaît pas ViewModelProvider, mais je n'ai pas du tout ces dépendances dans mes projets précédents et j'utilise LiveData et ViewModel absolument de la même manière (même les importations sont les mêmes) là-bas. Alors, qu'est-ce que je suis censé faire?

Réponses

1 AndrewChelix Nov 25 2020 at 11:52

Votre ViewModel nécessite un argument application: Applicationqui ne peut être fourni qu'en utilisant un ViewModelFactory comme ceci:

ViewModelFactory

class MainViewModelFactory(
    private val application: Application
) : ViewModelProvider.Factory {
    @Suppress("unchecked_cast")
    override fun <T : ViewModel?> create(modelClass: Class<T>): T {
        if (modelClass.isAssignableFrom(MainViewModel::class.java)) {
            return MainViewModel(application) as T
        }
        throw IllegalArgumentException("Unknown ViewModel class")
    }
}

Activité principale

private fun applyAdapterAndViewModel() {
// Not so kotlinic
mainViewModel = ViewModelProvider(this,MainViewModelFactory(application)).get(MainViewModel::class.java)
}

De plus, dans MainActivity, remplacez private lateinit var mainViewModel: MainViewModel par

private val viewModel by viewModels<MainViewModel> { 
MainViewModelFactory(application) }