Hilt: Question about activities/fragment context
See original GitHub issueHello guys, thanks for creating hilt,
Im currently playing with it and i love the leverage it creates, but im wondering how to properly inject activities/fragment context into view models and i have been facing some issues, can you guys provide with some guidance please?
I have a basic hilt skeleton:
LoginActivityModule
@Module
@InstallIn(ActivityRetainedComponent::class)
abstract class LoginActivityModule{
@Binds
@ActivityRetainedScoped
abstract fun provideLoginNavigator(impl: LoginNavigatorImpl): LoginNavigator
}
LoginViewModel
class LoginViewModel
@ViewModelInject constructor(val navigator: LoginNavigator) : ViewModel() { }
LoginNavigator and Impl
interface LoginNavigator {
fun toVerification(bundle: Bundle?)
}
class LoginNavigatorImpl @Inject constructor(private val activity: LoginActivity): LoginNavigator {
override fun toVerification(bundle: Bundle?) {
// code to navigate
}
LoginActivity
@AndroidEntryPoint
class LoginActivity : AppCompatActivity() {
private val loginViewModel: LoginViewModel by viewModels()
}
Stacktrace
[Dagger/MissingBinding] co.dummy.login.LoginActivity cannot be provided without an @Inject constructor or an @Provides-annotated method.
public abstract static class ApplicationC implements Dummy_GeneratedInjector,
^
A binding with matching key exists in component: co.dummy.Dummy_HiltComponents.ActivityC
co.dummy.login.LoginActivity is injected at
co.dummy.login.navigator.LoginNavigatorImpl(activity)
co.dummy.login.navigator.LoginNavigatorImpl is injected at
co.dummy.login.di.LoginActivityModule.provideLoginNavigator(impl)
javax.inject.Provider<co.ganapp.ui.login.navigator.LoginNavigator> is injected at
co.dummy.login.data.viewmodel.LoginViewModel_AssistedFactory(navigator)
co.dummy.login.data.viewmodel.LoginViewModel_AssistedFactory is injected at
co.dummy.login.data.viewmodel.LoginViewModel_HiltModule.bind(factory)
java.util.Map<java.lang.String,javax.inject.Provider<androidx.hilt.lifecycle.ViewModelAssistedFactory<? extends androidx.lifecycle.ViewModel>>> is injected at
androidx.hilt.lifecycle.ViewModelFactoryModules.ActivityModule.provideFactory(�, viewModelFactories)
@dagger.hilt.android.internal.lifecycle.DefaultActivityViewModelFactory java.util.Set<androidx.lifecycle.ViewModelProvider.Factory> is requested at
dagger.hilt.android.internal.lifecycle.DefaultViewModelFactories.ActivityEntryPoint.getActivityViewModelFactory() [co.dummy.Dummy_HiltComponents.ApplicationC ? co.dummy.Dummy_HiltComponents.ActivityRetainedC ? co.dummy.Dummy_HiltComponents.ActivityC]
The following other entry points also depend on it:
dagger.hilt.android.internal.lifecycle.DefaultViewModelFactories.FragmentEntryPoint.getFragmentViewModelFactory() [co.dummy.Dummy_HiltComponents.ApplicationC ? co.dummy.Dummy_HiltComponents.ActivityRetainedC ? co.dummy.Dummy_HiltComponents.ActivityC ? co.dummy.Dummy_HiltComponents.FragmentC]
FAILURE: Build failed with an exception.
With LoginActivityModule Updated
@Module
@InstallIn(ActivityRetainedComponent::class)
abstract class LoginActivityModule{
@Binds
@ActivityRetainedScoped
abstract fun provideLoginActivity(activity: LoginActivity): LoginActivity
@Binds
@ActivityRetainedScoped
abstract fun provideLoginNavigator(impl: LoginNavigatorImpl): LoginNavigator
}
Updated Stacktrace:
[Dagger/DependencyCycle] Found a dependency cycle:
public abstract static class ApplicationC implements Dummy_GeneratedInjector,
^
co.dummy.login.LoginActivity is injected at
co.dummy.login.di.LoginActivityModule.provideLoginActivity(activity)
co.dummy.login.LoginActivity is injected at
co.dummy.login.navigator.LoginNavigatorImpl(activity)
co.dummy.login.navigator.LoginNavigatorImpl is injected at
co.dummy.login.di.LoginActivityModule.provideLoginNavigator(impl)
javax.inject.Provider<co.ganapp.ui.login.navigator.LoginNavigator> is injected at
co.dummy.login.data.viewmodel.LoginViewModel_AssistedFactory(navigator)
co.dummy.login.data.viewmodel.LoginViewModel_AssistedFactory is injected at
co.dummy.login.data.viewmodel.LoginViewModel_HiltModule.bind(factory)
java.util.Map<java.lang.String,javax.inject.Provider<androidx.hilt.lifecycle.ViewModelAssistedFactory<? extends androidx.lifecycle.ViewModel>>> is injected at
androidx.hilt.lifecycle.ViewModelFactoryModules.ActivityModule.provideFactory(�, viewModelFactories)
@dagger.hilt.android.internal.lifecycle.DefaultActivityViewModelFactory java.util.Set<androidx.lifecycle.ViewModelProvider.Factory> is requested at
dagger.hilt.android.internal.lifecycle.DefaultViewModelFactories.ActivityEntryPoint.getActivityViewModelFactory() [co.dummy.Dummy_HiltComponents.ApplicationC ? co.dummy.Dummy_HiltComponents.ActivityRetainedC ? co.dummy.Dummy_HiltComponents.ActivityC]
The following other entry points also depend on it:
dagger.hilt.android.internal.lifecycle.DefaultViewModelFactories.FragmentEntryPoint.getFragmentViewModelFactory() [co.dummy.Dummy_HiltComponents.ApplicationC ? co.dummy.Dummy_HiltComponents.ActivityRetainedC ? co.dummy.Dummy_HiltComponents.ActivityC ? co.dummy.Dummy_HiltComponents.FragmentC]
FAILURE: Build failed with an exception.
Sorry if this is a very basic question, if you think this question is out of topic i can delete the post.
Issue Analytics
- State:
- Created 3 years ago
- Comments:5 (1 by maintainers)
Top Results From Across the Web
In Hilt, How can I Inject a context in a non activity/ fragment ...
So to clear. You want to get @ApplicationContext in IOException class. · yes i dont want to pass from constructor or from function,...
Read more >Dependency injection with Hilt | Android Developers
... Detect when users start an activity · Optimize location for battery · Test location workflows · Migrate to location and context APIs...
Read more >Hilt — say Hi! to the new generation dependency injection ...
Activities can create fragments and fragments are logically a subgraph of activities. Similarly, for views, the DI graph is different depending ...
Read more >Dagger Hilt Tutorial - Step by Step Guide - MindOrks
To understand it better in a basic way, think module as a provider of dependency and consider an activity or any other class...
Read more >Dagger Hilt in Android with Example - GeeksforGeeks
First, we annotate it with @AndroidEntryPoint annotation which will make the component class(activity, fragments, views, services, and broadcast ...
Read more >Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start FreeTop Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
Top GitHub Comments
As you cleared out the problem with injecting with
ActivityRetainedComponent
, I used the@ActivityContext private val context: Context
instead and go from there casting it as a fragment activityI wanted to add that
FragmentActivity
is also a default available binding in theActivityComponent
of Hilt, so you don’t need to cast it from@ActivityContext
.Also, not sure if you already went this route or not, but you should consider injecting your Navigator into your Activity and communicating between the ViewModel and Activity to perform the actual navigation whether if its on a click or some other login event possibly with an event subscription mechanism (LiveData, Rx, etc).