Dagger-Hilt: @ViewModelInject is not injecting MyViewModel and crash?
Solution 1
Apparently I miss out adding a kapt, which is kapt 'androidx.hilt:hilt-compiler:1.0.0-alpha01'
The list of dependencies in my build.gradle
is as below
implementation 'androidx.fragment:fragment-ktx:1.2.5'
implementation "androidx.lifecycle:lifecycle-viewmodel:2.2.0"
implementation "androidx.lifecycle:lifecycle-extensions:2.2.0"
implementation "androidx.hilt:hilt-lifecycle-viewmodel:1.0.0-alpha01"
implementation 'com.google.dagger:hilt-android:2.28-alpha'
kapt 'androidx.hilt:hilt-compiler:1.0.0-alpha01'
kapt 'com.google.dagger:hilt-android-compiler:2.28-alpha'
Just for completeness, the plugin is below
apply plugin: 'dagger.hilt.android.plugin'
apply plugin: 'kotlin-kapt'
Solution 2
@ViewModelInject
is deprecated in the newer hilt
version
https://developer.android.com/reference/androidx/hilt/lifecycle/ViewModelInject
Use HiltViewModel
@HiltViewModel
class TasksViewModel @Inject constructor(
val taskRepository: TaskRepository
) : ViewModel() {
}
Solution 3
I'd like to add that If you are on a multi-module project, you have to have kapt 'androidx.hilt:hilt-compiler:1.0.0-alpha01'
on the :app
module as well for it to work.
Solution 4
Try to search for your ViewModel's generated java files like below via Find in Path (⇧⌘F or Ctrl+Shift+F).
If there are no auto-generated java files. It means you forgot to add this dependency to your module's gradle file which generates necessary java files for every @HiltViewModel annotation.
kapt "androidx.hilt:hilt-compiler:$version"
Comments
-
Elye about 2 years
In exploring the ViewModelInject of Dagger-Hilt, I follow the example in https://developer.android.com/training/dependency-injection/hilt-jetpack#viewmodels
I try to inject the ViewModel into my activity as follow
import android.app.Application import androidx.appcompat.app.AppCompatActivity import android.os.Bundle import androidx.activity.viewModels import androidx.hilt.Assisted import androidx.hilt.lifecycle.ViewModelInject import androidx.lifecycle.* import androidx.savedstate.SavedStateRegistryOwner import dagger.hilt.android.AndroidEntryPoint import dagger.hilt.android.HiltAndroidApp import kotlinx.android.synthetic.main.activity_main.* import javax.inject.Inject import javax.inject.Singleton @HiltAndroidApp class MainApplication: Application() @AndroidEntryPoint class MainActivity : AppCompatActivity() { private val viewModel: MyViewModel by viewModels() private val textDataObserver = Observer<String> { data -> text_view.text = data } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) viewModel.showTextDataNotifier.observe(this, textDataObserver) btn_fetch.setOnClickListener { viewModel.fetchValue() } } } class MyViewModel @ViewModelInject constructor( @Assisted val savedStateHandle: SavedStateHandle, val repository: Repository ) : ViewModel(), LifecycleObserver { private val showTextLiveData = savedStateHandle.getLiveData<String>("DefaultKey") val showTextDataNotifier: LiveData<String> get() = showTextLiveData fun fetchValue() { showTextLiveData.value = repository.getMessage() } } @Singleton class Repository @Inject constructor() { fun getMessage() = "From Repository" }
It crash complaining
Caused by: java.lang.RuntimeException: Cannot create an instance of class com.elyeproj.simplehilt.MyViewModel 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:106) at androidx.hilt.lifecycle.HiltViewModelFactory.create(HiltViewModelFactory.java:69)
I try manually creating the ViewModel using the view model factory (the non-injection approach), it works fine.
import android.app.Application import androidx.appcompat.app.AppCompatActivity import android.os.Bundle import androidx.activity.viewModels import androidx.hilt.Assisted import androidx.hilt.lifecycle.ViewModelInject import androidx.lifecycle.* import androidx.savedstate.SavedStateRegistryOwner import dagger.hilt.android.AndroidEntryPoint import dagger.hilt.android.HiltAndroidApp import kotlinx.android.synthetic.main.activity_main.* import javax.inject.Inject import javax.inject.Singleton @HiltAndroidApp class MainApplication: Application() @AndroidEntryPoint class MainActivity : AppCompatActivity() { private val viewModel: MyViewModel by viewModels{ MyViewModelFactory(this, Repository(), intent.extras) } private val textDataObserver = Observer<String> { data -> text_view.text = data } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) viewModel.showTextDataNotifier.observe(this, textDataObserver) btn_fetch.setOnClickListener { viewModel.fetchValue() } } } class MyViewModelFactory( owner: SavedStateRegistryOwner, private val repository: Repository, defaultArgs: Bundle? = null ) : AbstractSavedStateViewModelFactory(owner, defaultArgs) { override fun <T : ViewModel> create(key: String, modelClass: Class<T>, handle: SavedStateHandle ): T { return MyViewModel( handle, repository ) as T } } class MyViewModel @ViewModelInject constructor( @Assisted val savedStateHandle: SavedStateHandle, val repository: Repository ) : ViewModel(), LifecycleObserver { private val showTextLiveData = savedStateHandle.getLiveData<String>("DefaultKey") val showTextDataNotifier: LiveData<String> get() = showTextLiveData fun fetchValue() { showTextLiveData.value = repository.getMessage() } } @Singleton class Repository @Inject constructor() { fun getMessage() = "From Repository" }
Did I do anything wrong in the use of
@ViewModelInject
? -
Sharad almost 4 yearsMy Problem was, I was using viewmodel in Fragment and on Fragment i didn't mention @AndroidEntryPoint. I mentioned that on Activity but not on Fragment.
-
Devarshi almost 4 yearsYou saved my day! I was missing implementation for "androidx.lifecycle:lifecycle-viewmodel:2.2.0"
-
A. Cedano almost 4 yearsI haved the same error. In my case, I was missing
implementation "androidx.lifecycle:lifecycle-viewmodel:2.2.0"
andimplementation "androidx.lifecycle:lifecycle-extensions:2.2.0"
. When I added that intoapp/build.gradle
the problem was solved. -
Andrew Chelix over 3 yearsI tried using this while doing the Android Testing course but I'm still getting this error: InstantiationException: java.lang.Class<com.example.android.architecture.blueprints.todoapp.tasks.TasksViewModel> has no zero argument constructor
-
Abdul Mateen about 3 yearsIf anyone like @AndrewChelix getting an issue even after adding the above answer then makes sure all hilt dependencies should be updated also.
-
Sagar Kacha almost 3 yearsThis saved my day!. Thanks!
-
Kirguduck over 2 years...and {Remove the old androidx.hilt:hilt-lifecycle-viewmodel dependency from your build.gradle file} from here - github.com/google/dagger/releases/tag/dagger-2.34