Cannot create an instance of class view model - Kotlin
Asked Answered
T

3

5

I'm currently working on a project to practice dependency injection with Dagger-Hilt, however I can't get my ViewModel to instantiate, I've already looked at some other questions on the same topic, most point the issue to Gradle but that didn't fix it for me, all errors in the Stacktrace are from internal classes except for the 2 lines that involve my ViewModel within the MainActivity

Here is the Stacktrace:

E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.practiceproject, PID: 9873
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.practiceproject/com.example.practiceproject.ui.MainActivity}: java.lang.RuntimeException: Cannot create an instance of class com.example.practiceproject.ui.viewmodel.DogViewModel
    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3270)
    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3409)
    at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:83)
    at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
    at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2016)
    at android.os.Handler.dispatchMessage(Handler.java:107)
    at android.os.Looper.loop(Looper.java:214)
    at android.app.ActivityThread.main(ActivityThread.java:7356)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930)
 Caused by: java.lang.RuntimeException: Cannot create an instance of class com.example.practiceproject.ui.viewmodel.DogViewModel
    at androidx.lifecycle.ViewModelProvider$NewInstanceFactory.create(ViewModelProvider.java:221)
    at androidx.lifecycle.ViewModelProvider$AndroidViewModelFactory.create(ViewModelProvider.java:278)
    at androidx.lifecycle.SavedStateViewModelFactory.create(SavedStateViewModelFactory.java:112)
    at androidx.lifecycle.SavedStateViewModelFactory.create(SavedStateViewModelFactory.java:146)
    at dagger.hilt.android.internal.lifecycle.HiltViewModelFactory.create(HiltViewModelFactory.java:111)
    at androidx.lifecycle.ViewModelProvider.get(ViewModelProvider.java:187)
    at androidx.lifecycle.ViewModelProvider.get(ViewModelProvider.java:150)
    at androidx.lifecycle.ViewModelLazy.getValue(ViewModelProvider.kt:54)
    at androidx.lifecycle.ViewModelLazy.getValue(ViewModelProvider.kt:41)
    at com.example.practiceproject.ui.MainActivity.getDogViewModel(MainActivity.kt:15)
    at com.example.practiceproject.ui.MainActivity.onCreate(MainActivity.kt:22)
    at android.app.Activity.performCreate(Activity.java:7802)
    at android.app.Activity.performCreate(Activity.java:7791)
    at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1299)
    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3245)
    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3409) 
    at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:83) 
    at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135) 
    at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95) 
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2016) 
    at android.os.Handler.dispatchMessage(Handler.java:107) 
    at android.os.Looper.loop(Looper.java:214) 
    at android.app.ActivityThread.main(ActivityThread.java:7356) 
    at java.lang.reflect.Method.invoke(Native Method) 
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492) 
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930) 
 Caused by: java.lang.InstantiationException: java.lang.Class<com.example.practiceproject.ui.viewmodel.DogViewModel> 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$AndroidViewModelFactory.create(ViewModelProvider.java:278) 
    at androidx.lifecycle.SavedStateViewModelFactory.create(SavedStateViewModelFactory.java:112) 
    at androidx.lifecycle.SavedStateViewModelFactory.create(SavedStateViewModelFactory.java:146) 
    at dagger.hilt.android.internal.lifecycle.HiltViewModelFactory.create(HiltViewModelFactory.java:111) 
    at androidx.lifecycle.ViewModelProvider.get(ViewModelProvider.java:187) 
    at androidx.lifecycle.ViewModelProvider.get(ViewModelProvider.java:150) 
    at androidx.lifecycle.ViewModelLazy.getValue(ViewModelProvider.kt:54) 
    at androidx.lifecycle.ViewModelLazy.getValue(ViewModelProvider.kt:41) 
    at com.example.practiceproject.ui.MainActivity.getDogViewModel(MainActivity.kt:15) 
    at com.example.practiceproject.ui.MainActivity.onCreate(MainActivity.kt:22) 
    at android.app.Activity.performCreate(Activity.java:7802) 
    at android.app.Activity.performCreate(Activity.java:7791) 
    at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1299) 
    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3245) 
    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3409) 
    at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:83) 
    at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135) 
    at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95) 
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2016) 
    at android.os.Handler.dispatchMessage(Handler.java:107) 
    at android.os.Looper.loop(Looper.java:214) 
    at android.app.ActivityThread.main(ActivityThread.java:7356) 
    at java.lang.reflect.Method.invoke(Native Method) 
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492) 
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930) 

Here is the ViewModel:

class DogViewModel @Inject constructor(
private val getDefaultImages: GetDefaultImages
) : ViewModel() {

val dogModel = MutableLiveData<DogModel>()
val isLoading = MutableLiveData<Boolean>()

fun onCreate() {
    viewModelScope.launch {
        isLoading.value = true
        val result = getDefaultImages()
        if(!result.isNullOrEmpty()) {
            dogModel.value = result[0]
            isLoading.value = false
        }
    }
}

And this is where I'm declaring it:

@AndroidEntryPoint
class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding

private val dogViewModel: DogViewModel by viewModels()

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    binding = ActivityMainBinding.inflate(layoutInflater)
    setContentView(binding.root)

    dogViewModel.onCreate()

    dogViewModel.dogModel.observe(this) {
        initRecyclerView(it)
    }
}
Then answered 25/5, 2022 at 18:10 Comment(2)
Do you somehow use getDefaultImages in DogViewModel? If not you can remove it and it will work.Polychrome
I do use it, on the onCreate method of the viewModel, it's an invoke function that I use to get info from an APIThen
F
15

You should add @HiltViewModel annotation on top of your view model.

Fernandefernandel answered 25/5, 2022 at 19:10 Comment(2)
I can't believe I forgot about that, fkin hell, thank youThen
bloody hell hahaha I did this mistake too. Thanks manLylelyles
S
5
  1. Make sure you have written @AndroidEntryPoint above your Fragment or Activity class.
  2. You have to write @HiltViewModel above your ViewModel Class.
  3. Also make sure you are providing all the dependencies written in ViewModel like repositories, etc.
Senility answered 20/12, 2022 at 13:58 Comment(0)
P
1

If don't use getDefaultImages object in DogViewModel you can remove it and it will work. If you use it you need to pass an instance of GetDefaultImages class to the DogViewModel using ViewModelProvider.Factory:

@Suppress("UNCHECKED_CAST")
private val factory: ViewModelProvider.Factory = object : ViewModelProvider.Factory {
    override fun <T : ViewModel> create(modelClass: Class<T>): T {
        return DogViewModel(GetDefaultImages()) as T
    }

}

private val dogViewModel: MyViewModel by viewModels { factory }
Polychrome answered 25/5, 2022 at 18:56 Comment(2)
Great, it worked, thank you very much. Is there any chance you've got the time to explain why? Because I don't think I understand what the problem was and how this fixed itThen
I thought I explained it in my answer: "you need to pass an instance of GetDefaultImages class to the DogViewModel using ViewModelProvider.Factory", viewModels() doesn't know what should be passed to the ViewModel's constructor.Polychrome

© 2022 - 2024 — McMap. All rights reserved.