Reputation: 1052
These are my hilt dependencies -
//Dagger Hilt
implementation "com.google.dagger:hilt-android:2.33-beta"
kapt "com.google.dagger:hilt-compiler:2.33-beta"
implementation 'androidx.hilt:hilt-lifecycle-viewmodel:1.0.0-alpha03'
kapt "androidx.hilt:hilt-compiler:1.0.0-beta01"
These are my two modules
AppModule.kt
@Module
@InstallIn(SingletonComponent::class) //scope - entire application
object AppModule {
@Singleton // single instance in application
@Provides // provide this dependency
@Named(Consts.String1) // name in case of conflict
fun provideTestString1() = "Injected String from String1"
}
MainModule.kt
@Module
@InstallIn(ActivityComponent::class) // scope - activities
object MainModule {
@ActivityScoped // single instance in Activity
@Provides // provide this dependency
@Named(Consts.String2) //name in case of conflict
fun provideTestString2(@ApplicationContext context:Context,@Named(Consts.String1) testStringFromApplication:String) = context.getString(R.string.string_to_inject) +" $testStringFromApplication"
}
This is my ViewModel
@HiltViewModel
class TestViewModel @Inject constructor(@Named(Consts.String2) testStringFromViewModel: String) : ViewModel() {
init {
Log.d(Consts.TAG, "String from viewModel : $testStringFromViewModel")
}
}
This is the activity where I am just trying to log the injected strings.
@AndroidEntryPoint
class MainActivity : AppCompatActivity() {
private val viewmodel : TestViewModel by viewModels() // injecting viewModel
@Inject
@Named(Consts.String1)
lateinit var testString : String
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
Log.d(Consts.TAG, testString)
viewmodel
}
}
Consts.kt
object Consts {
const val TAG = "mDependencyInjection"
const val String1 = "String1"
const val String2 = "String2"
}
The error
public abstract static class SingletonC implements MyApplication_GeneratedInjector,
^
@javax.inject.Named("String2") java.lang.String is injected at
com.example.daggerhilt.TestViewModel(testStringFromViewModel)
com.example.daggerhilt.TestViewModel is injected at
com.example.daggerhilt.TestViewModel_HiltModules.BindsModule.binds(vm)
@dagger.hilt.android.internal.lifecycle.HiltViewModelMap java.util.Map<java.lang.String,javax.inject.Provider<androidx.lifecycle.ViewModel>> is requested at
dagger.hilt.android.internal.lifecycle.HiltViewModelFactory.ViewModelFactoriesEntryPoint.getHiltViewModelMap() [com.example.daggerhilt.MyApplication_HiltComponents.SingletonC ? com.example.daggerhilt.MyApplication_HiltComponents.ActivityRetainedC ? com.example.daggerhilt.MyApplication_HiltComponents.ViewModelC]
When I Inject String 1 in the viewmodel it works fine but when I try to inject String 2 the viewmodel. The error above pops up.
Link to the tutorial I am following https://www.youtube.com/watch?v=ZE2Jkvnk2Bs&ab_channel=PhilippLackner
https://github.com/philipplackner/HiltTutorial
Upvotes: 6
Views: 7121
Reputation: 1001
A ViewModel outlives an Activity, so you cannot provide a dependency scoped to an Activity to a ViewModel. Your String1 dependency is scoped to Singleton, so it can be used everywhere, but String2 is scoped to an Activity, so it cannot be used in a ViewModel, which is why it doesn't work in your example.
Adjust MainModule to be scoped higher and it will work. You can see the scope hierarchy here. So to inject into a ViewModel, use anything above ActivityComponent
/@ActivityScoped
, such as
@Module
@InstallIn(ViewModelComponent::class)
object MainModule {
@Provides
@ViewModelScoped
@Named(Consts.String2)
fun provideTestString2(@ApplicationContext context:Context, @Named(Consts.String1) testStringFromApplication:String) = context.getString(R.string.string_to_inject) +" $testStringFromApplication"
}
Upvotes: 9