Chris Pi
Chris Pi

Reputation: 612

Getting error from creating a Hilt viewModel

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?

Upvotes: 9

Views: 15585

Answers (4)

Mirza Adil
Mirza Adil

Reputation: 412

Update

implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1'
kapt 'androidx.hilt:hilt-compiler:1.0.0'

Upvotes: 1

Mahdi Zareei
Mahdi Zareei

Reputation: 2028

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()
)

Upvotes: 7

Ehma Ugbogo
Ehma Ugbogo

Reputation: 428

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() 

Upvotes: 0

Mayur Gajra
Mayur Gajra

Reputation: 9073

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"

Upvotes: 4

Related Questions