Nathaniel Rowe
02/10/2022, 4:58 PMViewModel has no zero argument constructor
error when trying to construct a hilt view model in a compose function. Anyone else experiencing this? I'm not using the jetpack navigation component, just trying to inject a view model scoped to LocalViewModelStoreOwner.current. I get this error when trying to inject even a simple class with no sub-dependencies.
My view model is provided like this: viewModel: MyViewModel = viewModel()
, and I'm using the @HiltViewModel annotation on my view model. My activity and application all support hilt injection properly. I'm using the "androidx.lifecycle:lifecycle-viewmodel-compose" dependency for creating my view model. Let me know if you need more information.
Edit: this also only happens when trying to create the view model with any injected dependencies. If the view model has no dependencies, it works fine. The hiltViewModel()
is only supposed to be used with the navigation component, which I am not using. I am using an alternate navigation library (this one: https://github.com/olshevski/compose-navigation-reimagined), but from my understanding, it sets the LocalViewModelStoreOwner properly, and that's what the viewModel()
function uses. I'm assuming it's something to do with the view model factory.Colton Idle
02/10/2022, 5:00 PMNathaniel Rowe
02/10/2022, 5:02 PMColton Idle
02/10/2022, 5:09 PMAleksandar Aleksiev
02/10/2022, 6:12 PMviewModel
is using in this case HiltViewModelFactory
. As mentioned in the docs it will only work for Activity or Fragment annotated with @AndroidEntryPoint
https://dagger.dev/api/latest/dagger/hilt/android/lifecycle/HiltViewModel.htmlNathaniel Rowe
02/10/2022, 7:03 PMviewModel()
method automatically used the hilt view model factory. Is this not always the case? My application only has a single activity and no fragments, and is annotated as an android entry point.Aleksandar Aleksiev
02/10/2022, 8:07 PMhiltViewModel()
you will see that it creates an instance of HiltViewModelFactory
and pass it to the viewModel().
If there's no factory provided the viewModel()
uses the default factory of the ViewModelStoreOwner
which in this case is SavedStateViewModelFactory
Nathaniel Rowe
02/10/2022, 8:22 PMAleksandar Aleksiev
02/10/2022, 8:31 PMhilt-navigation-compose
viewModel
creates an instance of a @HiltViewModel
but after removing that dependency I got the same error that an instance of the model cannot be createdNathaniel Rowe
02/10/2022, 8:42 PMAleksandar Aleksiev
02/10/2022, 8:57 PMviewModel
Nathaniel Rowe
02/10/2022, 8:58 PMColton Idle
02/11/2022, 4:44 PMNathaniel Rowe
02/11/2022, 5:23 PMviewModel()
to create my view model, and I wasn't in the scope of an activity or fragment, for which viewModel()
can automatically use the hilt view model factory and make everything work.
By "scope" here I basically mean what the LocalViewModelStoreOwner composition local is currently set to. The navigation component sets this composition local to be the current destination's NavBackStackEntry, an object which implements the ViewModelStoreOwner interface. This breaks the ability of viewModel()
to create a hilt view model. As such, you use the hilt nav compose dependency to get the hiltViewModel()
function, which specifically detects when your LocalViewModelStoreOwner is a NavBackStackEntry, and uses the hilt view model factory in this case. Because it specifically checks for NavBackStackEntry, a navigation component object, it didn't work for my use case, which does not use navigation component.
My solution was to hack together a custom hiltViewModel()
function which does work with the navigation library I'm using. My solution wasn't perfect as I need access to some internal types of the library I used, but I opened a github discussion about adding hilt support so hopefully that will change in the future. I can share the code I used too if you need (which would only be the case if you are not using jetpack navigation component, btw).
If you are using the navigation component, my guess is that you either forgot to add the android entry point or hilt android app annotations to your activity/application class, that you aren't using hiltViewModel()
to create your view model, or the hilt nav compose version is incompatible with the navigation component version you are using. Otherwise, kinda sounds like a bug with the library to me, but it's hard to say. I do know the navigation component is a convoluted mess internally (I have combed through the source code quite a bit).
That being said, creating a custom hiltViewModel()
method probably would work as a temporary solution, if you really can't figure out what is wrong. But in my experience of using the navigation component, using hiltViewModel()
, when all else is set up correctly, should work unless something broke in a new version recently.Colton Idle
02/12/2022, 6:05 AM