question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Hilt: Question about activities/fragment context

See original GitHub issue

Hello 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:closed
  • Created 3 years ago
  • Comments:5 (1 by maintainers)

github_iconTop GitHub Comments

1reaction
ispamcommented, Jun 15, 2020

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 activity

0reactions
danysantiagocommented, Jun 15, 2020

I wanted to add that FragmentActivity is also a default available binding in the ActivityComponent 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).

Read more comments on GitHub >

github_iconTop 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 >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found