'HiltViewModel: Cannot create an instance of class
I am using Hilt. After updating to 1.0.0-alpha03
I got warnings that @ViewModelInject
is deprecated and I should use @HiltViewModel
. But when I change it I got an error:
java.lang.RuntimeException: Cannot create an instance of class com.example.LoginViewModel
...
Caused by: java.lang.NoSuchMethodException: com.example.LoginViewModel.<init> [class android.app.Application]
Previous my ViewModel looked like this:
class LoginViewModel @ViewModelInject constructor(
application: Application,
private val repository: RealtimeDatabaseRepository
) : AndroidViewModel(application)
Now it looks like this:
@HiltViewModel
class LoginViewModel @Inject constructor(
application: Application,
private val repository: RealtimeDatabaseRepository
) : AndroidViewModel(application)
Fragment where ViewModel is injected:
@AndroidEntryPoint
class LoginFragment : Fragment(R.layout.fragment_login)
{
private val viewModel: LoginViewModel by activityViewModels()
}
Injected class:
@Singleton
class RealtimeDatabaseRepository @Inject constructor() { }
When I deleted private val repository: RealtimeDatabaseRepository
from ViewModel constructor it is working
I was using hilt version 2.30.1-alpha
when I updated to 2.31.2-alpha
, as USMAN osman suggested, the error is gone.
Solution 1:[1]
With new hilt version lots of stuff has been changed.
You also have to upgrade your hilt android, hilt compiler and hilt gradle plugin to:2.31-alpha
I made mock sample exactly the way you did i had same issue, after going through hilt's docs i found new way to inject dependencies to viewModels, you have to make separate module for dependencies which are going to inject in the viewModel
with special component called ViewModelComponent
:
@Module
@InstallIn(ViewModelComponent::class) // this is new
object RepositoryModule{
@Provides
@ViewModelScoped // this is new
fun providesRepo(): ReposiotryIMPL { // this is just fake repository
return ReposiotryIMPL()
}
}
here is what docs says about ViewModelComponent
and ViewModelScoped
All Hilt View Models are provided by the ViewModelComponent which follows the same lifecycle as a ViewModel, i.e. it survives configuration changes. To scope a dependency to a ViewModel use the @ViewModelScoped annotation.
A @ViewModelScoped type will make it so that a single instance of the scoped type is provided across all dependencies injected into the Hilt View Model.
link: https://dagger.dev/hilt/view-model.html
then your viewModel:
@HiltViewModel
class RepoViewModel @Inject constructor(
application: Application,
private val reposiotryIMPL: ReposiotryIMPL
) : AndroidViewModel(application) {}
UPDATE
It is not mandatory that you should be using ViewModelComponent
or ViewModelScoped
as i did in the above example. You can also use other scopes
or components
depends on your usecase.
Furthermore read docs, i put the dagger-hilt's link above.
Solution 2:[2]
I've seen this happens when the Fragment/Activity that is using the ViewModel is missing the @AndroidEntryPoint annotation, for instance:
import androidx.fragment.app.viewModels
@AndroidEntryPoint
class SampleFragment: BaseFragment() {
val viewModel: SampleFragmentViewModel by viewModels()
}
If the annotation is not present, the exact same error you describe will happen.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | |
Solution 2 | Chepech |