7

I've tried to hand over a simple viewModel to a composable and get everytime this error and i don't know what it means:

java.lang.IllegalStateException: Given component holder class com.example.app.MainActivity does not implement interface dagger.hilt.internal.GeneratedComponent or interface dagger.hilt.internal.GeneratedComponentManager

My Gradle:

    implementation("androidx.hilt:hilt-navigation:1.0.0-beta01")
    implementation("androidx.hilt:hilt-lifecycle-viewmodel:1.0.0-alpha03")

I've created a BaseApplication file

import android.app.Application
import dagger.hilt.android.HiltAndroidApp

@HiltAndroidApp
class BaseApplication: Application()

and set it in the Manifest.

I've created an AppModule file:

import android.content.Context
import com.veloce.montageservice.BaseApplication
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.android.qualifiers.ApplicationContext
import dagger.hilt.components.SingletonComponent
import javax.inject.Singleton

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

    @Singleton
    @Provides
    fun provideApplication(@ApplicationContext app: Context): BaseApplication {
        return app as BaseApplication
    }
}

Then set the @HiltAndroidApp in my MainActivity and created a viewModel like this:

@HiltViewModel
class TaskViewModel: ViewModel() {

//code

}

The viewModel is called in my navigation at the MainActivity:

 val navController = rememberNavController()
 NavHost(
     navController = navController,
     startDestination = Screens.LoginScreen.route
 ) {
 composable(Screens.ActiveMontageScreen.route) { navBackStackEntry ->
     activeTask?.let {
         val factory =
             HiltViewModelFactory(LocalContext.current, navBackStackEntry)
         val viewModel: TaskViewModel = viewModel("taskViewModel", factory)
         ActiveMontageScreen(
             viewModel = viewModel,
             task = it,
             navigation = navController,
             context = LocalContext.current
         ) {
             removeActiveTask()
         }
     }
 }
}

I really cant't see any problems, but I am quite unexperienced with Hilt and Android Development. Does anyone know whats the problem?

Chris Pi
  • 536
  • 1
  • 5
  • 21

4 Answers4

4

There are few things misplaced as I can see, which lead to such error.

For example:

  1. You're not injecting the context here class TaskViewModel(context: Context) if you need context in viewmodel then you can use AndroidViewModel.

  2. you're creating BaseApplication in AppModule but you're not using it(Maybe used somewhere else).

You can create such viewmodel with following steps:

  1. Create BaseApplication & register that in manifest, which you have already done.

  2. Create a AndroidViewModel as following:

    @HiltViewModel
    class TaskViewModel @Inject constructor(
     application: BaseApplication
    ) : AndroidViewModel(application) {
    
     fun test() {
         getApplication<BaseApplication>().getString(R.string.app_name)
     }
    
    }  
    

Here notice the use of @Inject constructor which will take the BaseApplication class from AppModule.

  1. In your MainActivity initialize the viewmodel like this:

    @AndroidEntryPoint
    class MainActivity : AppCompatActivity() {
    
     private val viewModel: TaskViewModel by viewModels()
    
     override fun onCreate(savedInstanceState: Bundle?) {
         super.onCreate(savedInstanceState)
         setContentView(R.layout.activity_main)
    
         viewModel.test()
     }
    
    }
    

If you fail to resolve any of the hilt related things then make sure you have these dependencies in build.gradle

//Dagger - Hilt
    implementation "com.google.dagger:hilt-android:2.33-beta"
    kapt "com.google.dagger:hilt-android-compiler:2.33-beta"
    implementation "androidx.hilt:hilt-lifecycle-viewmodel:1.0.0-alpha03"
    kapt "androidx.hilt:hilt-compiler:1.0.0-beta01"
Mayur Gajra
  • 8,285
  • 6
  • 25
  • 41
  • That the context didnt made sense there was clear for me like 30 seconds after ive hitted the post button. :-) I've took it out and tried your suggestions but unfortunately nothing changed, same error – Chris Pi Apr 29 '21 at 15:29
  • I've saw that the annotation in `MainActivity` was wrong an changed it. I got a new error `java.lang.RuntimeException: Cannot create an instance of class com.example.app.ui.view_models.TaskViewModel` – Chris Pi Apr 29 '21 at 15:40
  • 1
    @ChrisPi Did you use `@Inject constructor` in `TaskViewModel`? If not then you should. Also, Did you try the method i gave you to initialize viewmodel in `MainActivity` ? – Mayur Gajra Apr 29 '21 at 15:47
  • Yes, I made the changes. I'm trying to implement kapt now – Chris Pi Apr 29 '21 at 15:51
  • I got it. The `classpath("com.google.dagger:hilt-android-gradle-plugin:2.33-beta")` and `id("dagger.hilt.android.plugin")` were missing. – Chris Pi Apr 29 '21 at 16:11
  • 1
    @ChrisPi Great. I hope you were able to fix it. – Mayur Gajra Apr 29 '21 at 16:31
4

please check these options:

1- you must have these dependencies:

//Hilt
def hilt_version = "2.38.1"
implementation("com.google.dagger:hilt-android:$hilt_version")
kapt("com.google.dagger:hilt-android-compiler:$hilt_version")
kapt("androidx.hilt:hilt-compiler:1.0.0")
implementation("androidx.hilt:hilt-navigation-compose:1.0.0-alpha03")
implementation("androidx.hilt:hilt-lifecycle-viewmodel:1.0.0-alpha03")

2- you must have added this annotation into your activity

@AndroidEntryPoint
class MainActivity : ComponentActivity()

3- you must have injected your viewModel in your screen like this

@Composable
fun MainScreen(
   viewModel: MainScreenViewModel = hiltViewModel()
)
Mahdi Zareei
  • 1,299
  • 11
  • 18
1

Update

implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1'
kapt 'androidx.hilt:hilt-compiler:1.0.0'
Mirza Adil
  • 352
  • 5
  • 9
0

So for you viewmodel, you'll need to add the annotation @Inject or @ViewModelInject depending on your version dependency and create it like this

class TaskViewModel @Inject constructor(context: Context) : ViewModel() {
    //code
}

And in your activity of fragment Instantiate this way

val taskViewModel: TaskViewModel by viewmodels() 
Ehma Ugbogo
  • 418
  • 5
  • 7