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.
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With