I am working with Android 14 api, Kotlin 2.0.0 and I'm using Hilt for dependency injection.
What is wrong with my Hilt config that is preventing the creation of the FirstViewModel
?
I get the following error:
java.lang.RuntimeException: Cannot create an instance of class
ui.viewmodels.FirstViewModel
...
Caused by: java.lang.NoSuchMethodException:
ui.viewmodels.FirstViewModel.<init> []
at java.lang.Class.getConstructor0(Class.java:3325)
at java.lang.Class.getDeclaredConstructor(Class.java:3063)
at androidx.lifecycle.viewmodel.internal.JvmViewModelProviders.createViewModel(JvmViewModelProviders.kt:38)
I have added an App class
@HiltAndroidApp
class App: Application()
I have added the App class to the AndroidManifest.xml
<application
android:name=".App"
My main activity has the @AndroidEntryPoint
annotation:
@AndroidEntryPoint
class MainActivity : ComponentActivity() {}
My Hilt module:
@Module
@InstallIn(SingletonComponent::class)
object DataModules {
@Provides
@Singleton
fun providesFirstApi(): FirstApi =
Retrofit.Builder().baseUrl("http://localhost:3000").addConverterFactory(
GsonConverterFactory.create()
).build().create(FirstApi::class.java)
@Provides
@Singleton
fun provideFirstRepository(firstApi: FirstApi): FirstRepository{
return FirstRepositoryImpl(firstApi)
}
}
The view model in question:
@HiltViewModel
class FirstViewModel @Inject constructor(private val firstRepository: FirstRepository): ViewModel() {
suspend fun getDetails() = firstRepository.getServices()
}
interface FirstRepository{
suspend fun getServices(): List<MyObject>
}
class FirstRepositoryImpl(private val firstApi: FirstApi): FirstRepository {
override suspend fun getServices() = listOf(MyObject())
}
import retrofit2.http.GET
interface FirstApi{
@GET("services")
suspend fun getServices(): List<MyObject>
}
The composable in which I am trying to inject:
@Composable
fun Details(
FirstViewModel: FirstViewModel = viewModel()
) {
// ...
}
The relevant parts of my module level gradle file:
plugins {
alias(libs.plugins.dagger.hilt.android)
}
dependencies {
ksp(libs.dagger.compiler)
ksp(libs.androidx.hilt.compiler)
implementation(libs.hilt.navigation.compose)
androidTestImplementation(libs.hilt.android.testing)
testImplementation(libs.hilt.android.testing)
implementation(libs.hilt.compiler)
implementation(libs.hilt.android)
}
The relevant parts of the version catalog:
[versions]
daggerCompiler = "2.48"
hiltCompilerVersion = "1.2.0"
androidxHiltNavigationCompose = "1.2.0"
hiltAndroidTesting = "2.51.1"
hiltCompiler = "2.51.1"
hiltAndroidVersion = "2.44"
daggerHiltAndroid = "2.44"
[libraries]
dagger-compiler = { module = "com.google.dagger:dagger-compiler", version.ref = "daggerCompiler" }
androidx-hilt-compiler = { module = "androidx.hilt:hilt-compiler", version.ref = "hiltCompilerVersion" }
hilt-navigation-compose = { module = "androidx.hilt:hilt-navigation-compose", version.ref = "androidxHiltNavigationCompose" }
hilt-android-testing = { module = "com.google.dagger:hilt-android-testing", version.ref = "hiltAndroidTesting" }
hilt-compiler = { module = "com.google.dagger:hilt-compiler", version.ref = "hiltCompiler" }
hilt-android = { module = "com.google.dagger:hilt-android", version.ref = "hiltAndroidVersion" }
[plugins]
dagger-hilt-android = { id = "com.google.dagger.hilt.android", version.ref = "daggerHiltAndroid" }
You are mixing three different Hilt versions:
hiltAndroidVersion
, daggerHiltAndroid
daggerCompiler
hiltAndroidTesting
, hiltCompiler
The idea of specifying the versions separately is that you can reuse the same version variable for multiple artifacts. Since you always want the same version for all of the above artifacts, remove all version entries except one (rename it to hilt
, for example) and set its version to 2.51.1
:
hilt = "2.51.1"
Now update the artifacts to only use this version instead.
Note: androidxHiltNavigationCompose
has an independent versioning and must stay separate (with version 1.2.0
).
With this out of the way you also need to update your module level gradle file.
Throw these two out:
ksp(libs.dagger.compiler)
ksp(libs.androidx.hilt.compiler)
And libs.hilt.compiler
needs to be provided to ksp
instead of implementation
:
ksp(libs.hilt.compiler)
That's it, with this cleaned up gradle setup your code should work.