Home > Net >  ViewModel has no zero Argument constructor. Have AndroidEntryPoint
ViewModel has no zero Argument constructor. Have AndroidEntryPoint

Time:02-05

Hey all I am having problems figuring out hilt with android. Ive googled around and I can't find this specific problem. I seem to getting a "View Model has no zero argument constructor". I saw on another post that it was for a missing @AndroidEntryPoint annotation in their main activity however I added that and at this point I am a little stumped.

So far I have an application class

@HiltAndroidApp
class RecipeApplication: Application() {
}

The main activity

@AndroidEntryPoint
class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        setContent {
            MaterialTheme {
                Surface(
                    modifier = Modifier.fillMaxSize(),
                    color = primaryBackgroundColor
                ) {
                    RecipeBookApp()
                }
            }
        }
    }
}

The View model

@HiltViewModel
class RecipeViewModel @Inject constructor(
    private val recipeRepo: RecipeRepo
) : ViewModel() {....}

and then the Composable setting up my UI.

@Composable
fun RecipeBookApp(
    navController: NavHostController = rememberNavController()
) {
    Log.d("GetRecipe", "Still in Recipe Screen About to make the call")

    val recipeViewModel = viewModel(modelClass = RecipeViewModel::class.java)

    var editMode by remember { mutableStateOf(false) }
    Scaffold(
        backgroundColor = primaryBackgroundColor,
        topBar = {
            val title = "Edit"
            Column {
                Row(Modifier.padding(10.dp)) {
                    NiceButton(title = title) {
                        editMode = !editMode
                    }
                }
            }
        },
        bottomBar = {
        }) { innerPadding ->
        NavHost(
            navController,
            RecipeScreen.Start.name
        ) {
            composable(route = RecipeScreen.Start.name) {
                RecipeGridScreen(
                    onGridButtonClick = {
                        navController.navigate(RecipeScreen.RecipePage.name)
                    }
                )
            }
            composable(route = RecipeScreen.RecipePage.name) {
                val state = recipeViewModel.recipeState.collectAsState()
                RecipeView(state.value)
            }
        }
    }
}

RecipeRepo

class RecipeRepo @Inject constructor(
    private val recipeApi: RecipeApi
    ) {
    suspend fun getAllRecipes(): RecipeList {
        return recipeApi.getRecipes()
    }
}

RecipeApi

interface RecipeApi {
    @GET("recipe/getRecipes")
    suspend fun getRecipes(): RecipeList
}

RecipeApiModule

@Module
@InstallIn(SingletonComponent::class)
object RecipeApiModule {

    @Provides
    @Singleton
    fun provideApi(builder: Retrofit.Builder): RecipeApi {
        return builder
            .build()
            .create(RecipeApi::class.java)
    }

    @Provides
    @Singleton
    fun provideRetrofit(): Retrofit.Builder {
        return Retrofit.Builder()
            .baseUrl(RECIPE_URL)
            .addConverterFactory(GsonConverterFactory.create())
    }
}

                                                                                   

Process: com.bunkware.bunkyrecipe, PID: 6287 java.lang.RuntimeException: Cannot create an instance of class com.bunkware.bunkyrecipe.ui.recipe.RecipeViewModel at androidx.lifecycle.ViewModelProvider$NewInstanceFactory.create(ViewModelProvider.kt:204) at androidx.lifecycle.ViewModelProvider$AndroidViewModelFactory.create(ViewModelProvider.kt:322) at androidx.lifecycle.ViewModelProvider$AndroidViewModelFactory.create(ViewModelProvider.kt:304) at androidx.lifecycle.ViewModelProvider$AndroidViewModelFactory.create(ViewModelProvider.kt:278) at androidx.lifecycle.SavedStateViewModelFactory.create(SavedStateViewModelFactory.kt:128) at androidx.lifecycle.ViewModelProvider.get(ViewModelProvider.kt:187) at androidx.lifecycle.ViewModelProvider.get(ViewModelProvider.kt:153) at androidx.lifecycle.viewmodel.compose.ViewModelKt.get(ViewModel.kt:215) at androidx.lifecycle.viewmodel.compose.ViewModelKt.viewModel(ViewModel.kt:156) at com.bunkware.bunkyrecipe.ui.RecipeGridScreenKt.RecipeGridScreen(RecipeGridScreen.kt:30) at com.bunkware.bunkyrecipe.ui.recipe.RecipeScreenKt$RecipeBookApp$2$1$1.invoke(RecipeScreen.kt:63) at com.bunkware.bunkyrecipe.ui.recipe.RecipeScreenKt$RecipeBookApp$2$1$1.invoke(RecipeScreen.kt:62) at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:116) at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:34) at androidx.navigation.compose.NavHostKt$NavHost$4$2.invoke(NavHost.kt:163) at androidx.navigation.compose.NavHostKt$NavHost$4$2.invoke(NavHost.kt:162) at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:107) at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:34) at androidx.compose.runtime.CompositionLocalKt.CompositionLocalProvider(CompositionLocal.kt:228) at androidx.compose.runtime.saveable.SaveableStateHolderImpl.SaveableStateProvider(SaveableStateHolder.kt:84) at androidx.navigation.compose.NavBackStackEntryProviderKt.SaveableStateProvider(NavBackStackEntryProvider.kt:65) at androidx.navigation.compose.NavBackStackEntryProviderKt.access$SaveableStateProvider(NavBackStackEntryProvider.kt:1) at androidx.navigation.compose.NavBackStackEntryProviderKt$LocalOwnersProvider$1.invoke(NavBackStackEntryProvider.kt:52) at androidx.navigation.compose.NavBackStackEntryProviderKt$LocalOwnersProvider$1.invoke(NavBackStackEntryProvider.kt:51) at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:107) at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:34) at androidx.compose.runtime.CompositionLocalKt.CompositionLocalProvider(CompositionLocal.kt:228) at androidx.navigation.compose.NavBackStackEntryProviderKt.LocalOwnersProvider(NavBackStackEntryProvider.kt:47) at androidx.navigation.compose.NavHostKt$NavHost$4.invoke(NavHost.kt:162) at androidx.navigation.compose.NavHostKt$NavHost$4.invoke(NavHost.kt:141) at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:116) at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:34) at androidx.compose.animation.CrossfadeKt$Crossfade$5$1.invoke(Crossfade.kt:133) at androidx.compose.animation.CrossfadeKt$Crossfade$5$1.invoke(Crossfade.kt:128) at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:107) at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:34) at androidx.compose.animation.CrossfadeKt.Crossfade(Crossfade.kt:142) at androidx.compose.animation.CrossfadeKt.Crossfade(Crossfade.kt:73) at androidx.navigation.compose.NavHostKt.NavHost(NavHost.kt:141) at androidx.navigation.compose.NavHostKt$NavHost$5.invoke(Unknown Source:13) at androidx.navigation.compose.NavHostKt$NavHost$5.invoke(Unknown Source:10) at androidx.compose.runtime.RecomposeScopeImpl.compose(RecomposeScopeImpl.kt:145) 2023-02-04 11:45:31.431 6287-6287 AndroidRuntime
com.bunkware.bunkyrecipe E at androidx.compose.runtime.ComposerImpl.recomposeToGroupEnd(Composer.kt:2375) at androidx.compose.runtime.ComposerImpl.skipCurrentGroup(Composer.kt:2643) at androidx.compose.runtime.ComposerImpl$doCompose$2$5.invoke(Composer.kt:3260) at androidx.compose.runtime.ComposerImpl$doCompose$2$5.invoke(Composer.kt:3238) at androidx.compose.runtime.SnapshotStateKt__DerivedStateKt.observeDerivedStateRecalculations(DerivedState.kt:341) at androidx.compose.runtime.SnapshotStateKt.observeDerivedStateRecalculations(Unknown Source:1) at androidx.compose.runtime.ComposerImpl.doCompose(Composer.kt:3238) at androidx.compose.runtime.ComposerImpl.recompose$runtime_release(Composer.kt:3203) at androidx.compose.runtime.CompositionImpl.recompose(Composition.kt:771) at androidx.compose.runtime.Recomposer.performRecompose(Recomposer.kt:1031) at androidx.compose.runtime.Recomposer.access$performRecompose(Recomposer.kt:125) at androidx.compose.runtime.Recomposer$runRecomposeAndApplyChanges$2$2.invoke(Recomposer.kt:534) at androidx.compose.runtime.Recomposer$runRecomposeAndApplyChanges$2$2.invoke(Recomposer.kt:503) at androidx.compose.ui.platform.AndroidUiFrameClock$withFrameNanos$2$callback$1.doFrame(AndroidUiFrameClock.android.kt:34) at androidx.compose.ui.platform.AndroidUiDispatcher.performFrameDispatch(AndroidUiDispatcher.android.kt:109) at androidx.compose.ui.platform.AndroidUiDispatcher.access$performFrameDispatch(AndroidUiDispatcher.android.kt:41) at androidx.compose.ui.platform.AndroidUiDispatcher$dispatchCallback$1.doFrame(AndroidUiDispatcher.android.kt:69) at android.view.Choreographer$CallbackRecord.run(Choreographer.java:1229) at android.view.Choreographer$CallbackRecord.run(Choreographer.java:1239) at android.view.Choreographer.doCallbacks(Choreographer.java:899) at android.view.Choreographer.doFrame(Choreographer.java:827) at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:1214) at android.os.Handler.handleCallback(Handler.java:942) at android.os.Handler.dispatchMessage(Handler.java:99) at android.os.Looper.loopOnce(Looper.java:201) at android.os.Looper.loop(Looper.java:288) at android.app.ActivityThread.main(ActivityThread.java:7872) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:936) Suppressed: kotlinx.coroutines.DiagnosticCoroutineContextException: [androidx.compose.runtime.PausableMonotonicFrameClock@dfc23f4, androidx.compose.ui.platform.MotionDurationScaleImpl@a07d71d, StandaloneCoroutine{Cancelling}@64f9d92, AndroidUiDispatcher@2d4c363] Caused by: java.lang.InstantiationException: java.lang.Class<com.bunkware.bunkyrecipe.ui.recipe.RecipeViewModel> has no zero argument constructor at java.lang.Class.newInstance(Native Method) at androidx.lifecycle.ViewModelProvider$NewInstanceFactory.create(ViewModelProvider.kt:202) ... 71 more

CodePudding user response:

Your error message says RecipeGridScreen inside your NavHost is calling viewModel(). As per the Hilt and Navigation Compose docs, you must always use hiltViewModel() when inside a NavHost so that Hilt can find the correct factory.

So:

  1. Add the hilt-navigation-compose dependency to your build.gradle file:
implementation("androidx.hilt:hilt-navigation-compose:1.0.0")
  1. Change all calls to viewModel() to hiltViewModel(). This is only required inside your NavHost, but it works everywhere, so you can do a find/replace of all instances if you'd like.
  • Related