https://kotlinlang.org logo
#compose
Title
# compose
n

Nathaniel Rowe

02/10/2022, 4:58 PM
I'm getting a
ViewModel 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.
c

Colton Idle

02/10/2022, 5:00 PM
Are you on 2.5.0-alpha of navigation? If so, go back down to 2.4.1 and you should be good.
n

Nathaniel Rowe

02/10/2022, 5:02 PM
I'm not using the navigation component
c

Colton Idle

02/10/2022, 5:09 PM
Sorry. There was a recently opened bug in dagger that looked identical and it had to do with navigation. On mobile but maybe you can find it
a

Aleksandar Aleksiev

02/10/2022, 6:12 PM
I don't thin
viewModel
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.html
n

Nathaniel Rowe

02/10/2022, 7:03 PM
My understanding was that the
viewModel()
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.
a

Aleksandar Aleksiev

02/10/2022, 8:07 PM
Unfortunately no. If you have a look at the
hiltViewModel()
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
n

Nathaniel Rowe

02/10/2022, 8:22 PM
Interesting, thanks for the input. The android docs claim otherwise (see here: https://developer.android.com/jetpack/compose/libraries#hilt). I guess I'll create a method to use the proper view model factory.
a

Aleksandar Aleksiev

02/10/2022, 8:31 PM
I had the same issue and just remembered that I only fixed it after adding dependency to
hilt-navigation-compose
And just checked, yes
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 created
n

Nathaniel Rowe

02/10/2022, 8:42 PM
So, in my situation, do you believe the fix is to supply the hilt view model factory to the view model function directly, or to add the hilt navigation compose dependency? I think I did add that dependency but it still didn't work.
a

Aleksandar Aleksiev

02/10/2022, 8:57 PM
Probably adding that dependency will jot work for you but I would try to use hilt view model factory as factory provider for the
viewModel
n

Nathaniel Rowe

02/10/2022, 8:58 PM
Okay, thanks a bunch!
c

Colton Idle

02/11/2022, 4:44 PM
I had this issue after I iupgraded nav. Downgraded nav. Now I upgraded a bunch of other deps because i was getting a dupe class issue when running tests, and now I get the issue stated in this thread. I already have the hilt nav compose dep. Anyone find a solution?
n

Nathaniel Rowe

02/11/2022, 5:23 PM
Are you using navigation component or a different navigation library?
I can speak a bit on the solution I found and why it works. The specific error was because the view model was not being constructed using the hilt view model factory. I was using
viewModel()
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.
c

Colton Idle

02/12/2022, 6:05 AM
Thanks. I downgraded at 2.5.0-alpha to 2.4.0 and im back in business.
541 Views