40

Here is my AllFilesListViewModel class.

class AllFilesListViewModel @ViewModelInject constructor(
    private val pdfItemRepository: PdfItemRepository):ViewModel() {

}

Here is PdfItemRepository class.

@Singleton
class PdfItemRepository @Inject constructor(private val pdfItemDao: PdfItemDao){

}

For pdfItemDao. I created a module named DatabaseModule. Below is the code -

@Module
@InstallIn(ApplicationComponent::class)
object DatabaseModule {

    @Provides
    fun provideDatabase(@ApplicationContext context: Context):AppDatabase{
        return AppDatabase.getDataBase(context)
    }

    @Provides
    fun providePdfItemDao(database:AppDatabase):PdfItemDao{
        return database.pdfItemDao()
    }
}

Here is the fragment class AllFilesFragment.kt where I am using viewModel.

@AndroidEntryPoint
class AllFilesFragment:Fragment(){

    private lateinit var binding:AllFilesFragmentBinding
    private val viewModel by viewModels<AllFilesListViewModel>()


    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        binding = AllFilesFragmentBinding.inflate(inflater,container,false)
        context?: return binding.root
        initThings()
        subscribeUi()
        return binding.root
    }
}

Here is logcat file.

06-19 19:22:20.203 23753-23753/com.emptysheet.pdfreader_autoscroll E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.emptysheet.pdfreader_autoscroll, PID: 23753
    java.lang.RuntimeException: Cannot create an instance of class com.emptysheet.pdfreader_autoscroll.homeScreen.viewModel.AllFilesListViewModel
        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)
        at androidx.lifecycle.AbstractSavedStateViewModelFactory.create(AbstractSavedStateViewModelFactory.java:69)
        at androidx.lifecycle.ViewModelProvider.get(ViewModelProvider.java:185)
        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.emptysheet.pdfreader_autoscroll.homeScreen.AllFilesFragment.getViewModel(AllFilesFragment.kt)
        at com.emptysheet.pdfreader_autoscroll.homeScreen.AllFilesFragment.subscribeUi(AllFilesFragment.kt:72)
        at com.emptysheet.pdfreader_autoscroll.homeScreen.AllFilesFragment.onCreateView(AllFilesFragment.kt:64)
        at androidx.fragment.app.Fragment.performCreateView(Fragment.java:2698)
        at androidx.fragment.app.FragmentStateManager.createView(FragmentStateManager.java:320)
        at androidx.fragment.app.FragmentManager.moveToState(FragmentManager.java:1187)
        at androidx.fragment.app.FragmentManager.moveToState(FragmentManager.java:1356)
        at androidx.fragment.app.FragmentManager.moveFragmentToExpectedState(FragmentManager.java:1434)
        at androidx.fragment.app.BackStackRecord.executeOps(BackStackRecord.java:442)
        at androidx.fragment.app.FragmentManager.executeOps(FragmentManager.java:2169)
        at androidx.fragment.app.FragmentManager.executeOpsTogether(FragmentManager.java:1992)
        at androidx.fragment.app.FragmentManager.removeRedundantOperationsAndExecute(FragmentManager.java:1947)
        at androidx.fragment.app.FragmentManager.execSingleAction(FragmentManager.java:1818)
        at androidx.fragment.app.BackStackRecord.commitNow(BackStackRecord.java:297)
        at androidx.viewpager2.adapter.FragmentStateAdapter.placeFragmentInViewHolder(FragmentStateAdapter.java:341)
        at androidx.viewpager2.adapter.FragmentStateAdapter.onViewAttachedToWindow(FragmentStateAdapter.java:276)
        at androidx.viewpager2.adapter.FragmentStateAdapter.onViewAttachedToWindow(FragmentStateAdapter.java:67)
        at androidx.recyclerview.widget.RecyclerView.dispatchChildAttached(RecyclerView.java:7556)
        at androidx.recyclerview.widget.RecyclerView$5.addView(RecyclerView.java:860)
        at androidx.recyclerview.widget.ChildHelper.addView(ChildHelper.java:107)
        at androidx.recyclerview.widget.RecyclerView$LayoutManager.addViewInt(RecyclerView.java:8601)
        at androidx.recyclerview.widget.RecyclerView$LayoutManager.addView(RecyclerView.java:8559)
        at androidx.recyclerview.widget.RecyclerView$LayoutManager.addView(RecyclerView.java:8547)
        at androidx.recyclerview.widget.LinearLayoutManager.layoutChunk(LinearLayoutManager.java:1641)
        at androidx.recyclerview.widget.LinearLayoutManager.fill(LinearLayoutManager.java:1587)
        at androidx.recyclerview.widget.LinearLayoutManager.onLayoutChildren(LinearLayoutManager.java:665)
        at androidx.recyclerview.widget.RecyclerView.dispatchLayoutStep2(RecyclerView.java:4134)
        at androidx.recyclerview.widget.RecyclerView.dispatchLayout(RecyclerView.java:3851)
        at androidx.recyclerview.widget.RecyclerView.onLayout(RecyclerView.java:4404)
        at android.view.View.layout(View.java:15689)
        at android.view.ViewGroup.layout(ViewGroup.java:5048)
        at androidx.viewpager2.widget.ViewPager2.onLayout(ViewPager2.java:527)
        at android.view.View.layout(View.java:15689)
        at android.view.ViewGroup.layout(ViewGroup.java:5048)
        at com.google.android.material.appbar.HeaderScrollingViewBehavior.layoutChild(HeaderScrollingViewBehavior.java:148)
        at com.google.android.material.appbar.V
Bartek Lipinski
  • 30,698
  • 10
  • 94
  • 132
Rajesh kumar
  • 982
  • 1
  • 9
  • 17

12 Answers12

76

This happens to me when using Hilt , and that was because I forgot to add the @AndroidEntryPoint annotation on top of the fragment class. Both the fragment and the host activity should be annotated with this annotation.

Mohammed Fathi
  • 1,237
  • 1
  • 14
  • 12
  • 1
    If we annotate both Activity and Fragment with `AndroidEntryPoint` we will end up with issue mentioned https://stackoverflow.com/questions/63189892/hilt-fragments-must-be-attached-to-an-androidentrypoint-activity-found-class – Prasad G Kulkarni Jul 26 '22 at 10:41
  • @PrasadGKulkarni We can annotate multiple classes with `AndroidEntryPoint` – IgorGanapolsky Mar 10 '23 at 12:55
27

This got solved after I used kapt 'androidx.hilt:hilt-compiler:1.0.0-alpha01' in app's build.gradle. I had already added kapt "com.google.dagger:hilt-android-compiler:2.28-alpha". I still didn't understand the difference between two BTW. If anyone knows. Please explain it to me.

Rajesh kumar
  • 982
  • 1
  • 9
  • 17
  • 5
    To support `@ViewModelInject`, you have to enable code generation deps also. Please [official docs](https://developer.android.com/training/dependency-injection/hilt-jetpack) for more details – theapache64 Jul 31 '20 at 12:42
  • 3
    This solved my issue. To think I lost so much time because I didn't take a closer look at the docs. @Rajesh, I think the link in theapache64's comment might provide some explanation. – Eaweb Aug 17 '20 at 11:43
13

This is caused by a version mismatch between AndroidX Lifecycle, AndroidX Core, AndroidX Activity and AndroidX Fragment.

Hilt only works if getDefaultViewModelProviderFactory can be overridden.

This is only true if that method actually exists, which it doesn't if your dependencies are out of date. Namely, your androidx.fragment is lower than 1.2.0, and your androidx.activity is lower than 1.1.0.

Use this and it'll work:

implementation "androidx.appcompat:appcompat:1.4.1"
implementation "androidx.core:core-ktx:1.7.0"
implementation "androidx.activity:activity-ktx:1.4.0"
implementation "androidx.fragment:fragment-ktx:1.4.1"
implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.4.1'

implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.4.1"
implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.4.1"
implementation "androidx.lifecycle:lifecycle-runtime-ktx:2.4.1"
implementation "androidx.lifecycle:lifecycle-viewmodel-savedstate:2.4.1"

But currently, this is what makes it work for me:

buildscript {
    ext {
        dagger_version = '2.41'
    }

dependencies {
    classpath "com.google.dagger:hilt-android-gradle-plugin:$dagger_version"
}

and

apply plugin: 'dagger.hilt.android.plugin'
apply plugin: 'kotlin-kapt'

implementation "com.google.dagger:dagger:$dagger_version"
kapt "com.google.dagger:dagger-compiler:$dagger_version"
implementation "com.google.dagger:hilt-android:$dagger_version"
kapt "com.google.dagger:hilt-android-compiler:$dagger_version"
kaptTest "com.google.dagger:hilt-android-compiler:$dagger_version"
kaptAndroidTest "com.google.dagger:hilt-android-compiler:$dagger_version"
kapt 'androidx.hilt:hilt-compiler:1.0.0'
EpicPandaForce
  • 79,669
  • 27
  • 256
  • 428
10

@ViewModelInject is deprecated in the newer hilt version

Reference

Use HiltViewModel

@HiltViewModel
class AllFilesListViewModel @Inject constructor(
    val pdfItemRepository: PdfItemRepository)
) : ViewModel() {

}
Vatsal kesarwani
  • 664
  • 8
  • 23
8

When I use Jetpack Compose, Hilt and Compose Navigation, my approach is to get all the dependencies in the docs, and make sure that all of their versions are up-to-date. The key is when you create ViewModel, you shouldn't use = viewModel() beacause you have use Compose Navigation, = hiltViewModel() should be used instead.

Google cheatsheet link

JeckOnly
  • 347
  • 2
  • 10
  • More can be found here: https://developer.android.com/jetpack/compose/libraries#hilt – Rafael Dec 16 '21 at 04:49
  • in the docs, it sitll used = viewModel. It is wrong!!It is update!!But the docs has not changed. The lazy editor.... – JeckOnly Dec 18 '21 at 15:33
  • 1
    juniyan, thank you! Your comment on using hiltViewModel() instead of viewModel() did solve my issue. I had been struggling for past couple of days with this issue. Strange that Android documentation has it incorrect. – vn1gam Feb 13 '22 at 02:01
6

Jetpack Compose + ViewModel in NavGraph

This answer is for people who using Jetpack Compose and navigation (NavGraph) According to Hilt and Navigation in documentation we have to use hiltViewModel instead of viewModel Example:

dependencies {
    implementation("androidx.hilt:hilt-navigation-compose:1.0.0")
}
// import androidx.hilt.navigation.compose.hiltViewModel

@Composable
fun MyApp() {
    NavHost(navController, startDestination = startRoute) {
        composable("example") { backStackEntry ->
            // Creates a ViewModel from the current BackStackEntry
            // Available in the androidx.hilt:hilt-navigation-compose artifact
            val viewModel = hiltViewModel<MyViewModel>()
            MyScreen(viewModel)
        }
        /* ... */
    }
}

More and fresh information in the source

FreePhoenix888
  • 4,510
  • 3
  • 13
  • 22
2

I faced this issue before and I have fixed it by passing SavedStateHandle to the main constructor of the view model.

class AuthViewModel @ViewModelInject constructor(@Assisted private val savedState: SavedStateHandle) : ViewModel()

UPDATE 5/03/2023
In order to inject into a ViewModel with Hilt, please use:

@HiltViewModel
class AuthViewModel @Inject constructor() : ViewModel()
Amjad Alwareh
  • 2,926
  • 22
  • 27
0

For those who checked all the above solutions and still not working then the final check is to delete the Build folder and rebuild the project this will force the compiler to re-create the dagger dependency graph under the hood.

In my case, I have annotated my activity with @AndroidEntryPoint still facing the same issue. I have deleted my build folder and rebuild the project and it is working as expected.

Fazal Hussain
  • 1,129
  • 12
  • 28
0

In alpha03, Use the new @HiltViewModel and the normal @Inject now as shown below.

@HiltViewModel
class MyViewModel @Inject constructor(
    private val repository: Repository,
    private val savedStateHandle: SavedStateHandle
) : ViewModel(), LifecycleObserver {

    // Some code
}
0

I have also faced this problem today, I tried all the possible fixes suggested but it was impossible to remove the error. I just post my solution here in case someone has the same problem in the future.

In my case I have a multi-module project, with 'UI module', 'ViewModel module' and 'Use-cases module'. The error on my side was that I was not importing all the modules in the application's gradle module, I was only importing UI module. I found this note in the Android developers website regarding hilt implementation:

Note: Because Hilt's code generation needs access to all of the Gradle modules that use Hilt, the Gradle module that compiles your Application class also needs to have all of your Hilt modules and constructor-injected classes in its transitive dependencies.

When I imported all the modules that were needed to generate the DI graph, this crash disappeared.

Luis Pascual
  • 256
  • 1
  • 3
  • 13
0

for me resolvec when moved = viewModel() from Compose function to Activity

abbasalim
  • 3,118
  • 2
  • 23
  • 45
0

Add @AndroidEntryPoint top of class name inside your Fragment or Activity.

Like this:

@AndroidEntryPoint
class YourClassNameFragment: Fragment() {
    ....
}
Mikhail Guliaev
  • 1,168
  • 1
  • 6
  • 14