1

I'm currently working on a countdown app, and whenever I open it, it fails with a message saying Cannot create instance of class com.nailuj29gaming.CountdownViewModel

The stack trace is

    Process: com.nailuj29gaming.countdown.debug, PID: 17800
    java.lang.RuntimeException: Unable to start activity ComponentInfo{com.nailuj29gaming.countdown.debug/com.nailuj29gaming.countdown.MainActivity}: java.lang.RuntimeException: Cannot create an instance of class com.nailuj29gaming.countdown.CountdownViewModel
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2750)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2811)
        at android.app.ActivityThread.-wrap12(ActivityThread.java)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1528)
        at android.os.Handler.dispatchMessage(Handler.java:102)
        at android.os.Looper.loop(Looper.java:154)
        at android.app.ActivityThread.main(ActivityThread.java:6316)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:872)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:762)
     Caused by: java.lang.RuntimeException: Cannot create an instance of class com.nailuj29gaming.countdown.CountdownViewModel
        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.nailuj29gaming.countdown.MainActivity.onCreate(MainActivity.kt:23)
        at android.app.Activity.performCreate(Activity.java:6757)
        at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1119)
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2703)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2811) 
        at android.app.ActivityThread.-wrap12(ActivityThread.java) 
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1528) 
        at android.os.Handler.dispatchMessage(Handler.java:102) 
        at android.os.Looper.loop(Looper.java:154) 
        at android.app.ActivityThread.main(ActivityThread.java:6316) 
        at java.lang.reflect.Method.invoke(Native Method) 
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:872) 
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:762) 
     Caused by: java.lang.InstantiationException: java.lang.Class<com.nailuj29gaming.countdown.CountdownViewModel> has no zero argument constructor
        at java.lang.Class.newInstance(Native Method)
        at androidx.lifecycle.ViewModelProvider$NewInstanceFactory.create(ViewModelProvider.java:219)
        at androidx.lifecycle.ViewModelProvider.get(ViewModelProvider.java:187) 
        at androidx.lifecycle.ViewModelProvider.get(ViewModelProvider.java:150) 
        at com.nailuj29gaming.countdown.MainActivity.onCreate(MainActivity.kt:23) 
        at android.app.Activity.performCreate(Activity.java:6757) 
        at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1119) 
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2703) 
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2811) 
        at android.app.ActivityThread.-wrap12(ActivityThread.java) 
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1528) 
        at android.os.Handler.dispatchMessage(Handler.java:102) 
        at android.os.Looper.loop(Looper.java:154) 
        at android.app.ActivityThread.main(ActivityThread.java:6316) 
        at java.lang.reflect.Method.invoke(Native Method) 
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:872) 
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:762) 

I know there is a very similar question, this one, but that is target at Java, and my code is written in Kotlin. My ViewModel class's text is

package com.nailuj29gaming.countdown

import android.app.Application
import androidx.lifecycle.AndroidViewModel
import androidx.lifecycle.LiveData
import androidx.lifecycle.viewModelScope
import kotlinx.coroutines.launch

class CountdownViewModel(application: Application) : AndroidViewModel(application) {
    private val repo: CountdownRepo
    val countdowns: LiveData<List<Countdown>>

    init {
        val countdownDao = AppDatabase.getDatabase(application).countdownDao()
        repo = CountdownRepo(countdownDao)
        countdowns = repo.countdowns

    }

    fun insert(countdown: Countdown) = viewModelScope.launch {
        repo.insert(countdown)
    }

    fun delete(countdown: Countdown) = viewModelScope.launch {
        repo.delete(countdown)
    }
}

I create the ViewModel in the first line of my MainActivity.onCreate() method. The code I used to create it is viewModel = ViewModelProvider(this).get(CountdownViewModel::class.java)

My build.gradle file (at least what matters in this question) is

apply plugin: 'kotlin-kapt'

dependencies {
    def room_version = "2.2.3"
    def lifecycle_version = "2.2.0"
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
    implementation 'androidx.appcompat:appcompat:1.1.0'
    implementation 'androidx.core:core-ktx:1.1.0'
    implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
    testImplementation 'junit:junit:4.13'
    androidTestImplementation 'androidx.test.ext:junit:1.1.1'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
    implementation 'com.google.code.gson:gson:2.8.6'
    implementation 'androidx.preference:preference:1.1.0'
    implementation 'net.steamcrafted:materialiconlib:1.1.5'
    implementation 'com.google.android.material:material:1.0.0'
    implementation "androidx.room:room-runtime:$room_version"
    kapt "androidx.room:room-compiler:$room_version"
    implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:$lifecycle_version"
    implementation "androidx.room:room-ktx:$room_version"
}

I tried using a factory, but the ViewModelProviders class is deprecated deprecation

When I used a delegate, the IDE did not give me an error, but the compiler said

Cannot inline bytecode built with JVM target 1.8 into bytecode that is being built with JVM target 1.6. Please specify proper '-jvm-target' option

My code is compiled into bytecode built with JVM target 1.8, so this error shouldn't show, right?

Nailuj29
  • 463
  • 3
  • 15

3 Answers3

4

You need to upgrade to Fragment 1.2.0 or higher, which is what adds a support for the ViewModelProvider constructor as per the Lifecycle 2.2.0 release notes:

You can pass a Fragment or FragmentActivity to the new ViewModelProvider(ViewModelStoreOwner) constructor to achieve the same functionality when using Fragment 1.2.0.

When using an older version of Fragments (i.e., the Fragment 1.1.0 that AppCompat 1.1.0 pulls in), you'll only get the ViewModelProvider$NewInstanceFactory you see in your exception trace, rather than a ViewModel.Factory that supports AndroidViewModel.

Therefore you should add an explicit dependency on Fragment 1.2.1 (the current latest):

implementation 'androidx.fragment:fragment:1.2.1'
ianhanniballake
  • 155,909
  • 19
  • 351
  • 362
  • Note that if you included `fragment-ktx` of even 1.1.0, you'd get the right behavior when using `val viewModel: CountdownViewModel by viewModels()` - you never needed to use `ViewModelProviders.of()` in Kotlin. – ianhanniballake Feb 14 '20 at 21:26
  • I edited my question with the compilation error produced when I tried your method. – Nailuj29 Feb 14 '20 at 21:36
  • It sounds like you're missing the `kotlinOptions` section mentioned on the [Java8 Support documentation page](https://developer.android.com/studio/write/java8-support). – ianhanniballake Feb 14 '20 at 21:41
  • Our app includes both the old and the new androidx.fragment dependencies. How come, on some devices it works perfect, while others experience this crash? Is that random? Or do users with certain conditions always get the crash? – Entreco Mar 25 '20 at 08:34
  • @Entreco - apps can only have one version of a dependency in their apk - the latest version is always chosen by Gradle. – ianhanniballake Mar 25 '20 at 13:40
0

This post helped me, as I was facing a similar issue: https://stackoverflow.com/a/60670866/6030520

To address the error you were getting (Cannot inline bytecode built with JVM target 1.8 into bytecode that is being built with JVM target 1.6. Please specify proper '-jvm-target' option), you can simply add:

android { 

    ...

    kotlinOptions { jvmTarget = "1.8" }

}

... to your app/build.gradle file.

Jamie
  • 129
  • 1
  • 7
-1

You should consider this line from the stacktrace

Caused by: java.lang.InstantiationException: java.lang.Class has no zero argument constructor

This means you should pass an argument in the constructor when you buildng your viewmodel

In the link you quoted there is a specific kotlin answer]1

EDIT: And also control that you have correctly insta intiated the factory as shown in this response or this other one

trocchietto
  • 2,388
  • 1
  • 19
  • 33
  • What do you mean by pass an argument to the constructor? I thought when creating a ViewModel, the class must have a a single argument constructor with an `Application` argument. – Nailuj29 Feb 14 '20 at 20:27
  • please see my edit, you may need to check your `build.gradle` file and change annotation processor with `kapt` as in kotlin is recommended – trocchietto Feb 14 '20 at 20:28
  • I tried the kotlin answer to that question, and it didn't do anything – Nailuj29 Feb 14 '20 at 20:29
  • you mean you checked the gradle file and you do not use annotation processor? – trocchietto Feb 14 '20 at 20:30
  • Yes. I will add the build.gradle file to my question – Nailuj29 Feb 14 '20 at 20:31
  • I believe you:) what is important is how you instantiated from the activity the viewModel, did you use a factory as shown in my edit @Nailuij29 ? – trocchietto Feb 14 '20 at 20:35
  • 1
    No, I did not use a factory. I will try that – Nailuj29 Feb 14 '20 at 20:37
  • there is also a second example I linked even easier in my edit to use the factory. I agree that is confusing but save some boilerplate code – trocchietto Feb 14 '20 at 20:40
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/207861/discussion-between-nailuj29-and-trocchietto). – Nailuj29 Feb 14 '20 at 20:57