11

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.

iknow
  • 8,358
  • 12
  • 41
  • 68
  • 2
    does your activity have `@AndroidEntryPoint` too? Also, you don't need a `@Provides` method for classes that have an `@Inject` constructor annotation – IR42 Feb 04 '21 at 12:35
  • Yes, Activity has `@AndroidEntryPoint`. But if I want my repository to be a singleton I don't have to make `@Provides`? Can I annotate a class with `@Singleton` and it will be enough? – iknow Feb 04 '21 at 12:44
  • yes, you can annotate classes with a scope annotations `@Singleton class RealtimeDatabaseRepository @Inject constructor() { }` – IR42 Feb 04 '21 at 12:46
  • Okay, thanks. I deleted provide function but the error is still the same – iknow Feb 04 '21 at 12:48

3 Answers3

13

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.

USMAN osman
  • 952
  • 7
  • 13
  • 1
    Thanks, it is working now. The only thing I had to do was to update dependencies to `2.31-alpha` – iknow Feb 04 '21 at 18:02
  • 2
    Omg, I forgot to update the kapt and I struggled like 5 hours finding the solution to why this is not working ... after reading the answer 5 times I figured it out, triple check the versions if your app crash – Marian Pavel Feb 05 '21 at 17:14
  • 1
    it is fine to use a @Singleton scope as well, if you want to outlive the ViewModel: @InstallIn(SingletonComponent::class) – Henk-Martijn Feb 10 '21 at 20:22
  • I can confirm that updating the dependencies is sometimes the only thing missing to make the error go away. The `hilt-android` and `hilt-android-compiler` need to have the same version. – Tom Ladek Feb 25 '22 at 07:12
9

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.

Chepech
  • 5,258
  • 4
  • 47
  • 70
1

My error was a dumb one which might help future people, adding a ViewModel to a feature module I forgot to add the kapt and hilt dependencies to the feature's build.gradle file, meaning Hilt would never see the ViewModel.

Daniel Wilson
  • 18,838
  • 12
  • 85
  • 135