3

I wanted to have @Named qualifier for object that's returned from @Binds method, but I noticed that's only possible through static provides method, which I couldn't figure out in practical implementation. So below is what I wanted to achieve.

I have a custom UserScope, which would contain all activities/fragments/viewModels after user logged in, I have LoginViewModel in AuthViewModelModule and LeadViewModel an other VM in UserViewModelModule both VMModule binds VMProvider.Factory and for that reason I need to have @Named qualifier for the VMFactory instance, so I could inject @Named ones in respective activities/fragments.

@Module
internal abstract class AuthViewModelModule {

    @Binds
    @IntoMap
    @ViewModelKey(LoginViewModel::class)
    internal abstract fun bindLoginViewModel(loginViewModel: LoginViewModel): ViewModel

    @Binds
    internal abstract fun bindViewModelFactory(factory: AuthViewModelFactory):
        ViewModelProvider.Factory
}

@Module
internal abstract class UserViewModelModule {

    @Binds
    @IntoMap
    @ViewModelKey(LeadViewModel::class)
    internal abstract fun bindLeadViewModel(leadViewModel: LeadViewModel): ViewModel

    @Binds
    internal abstract fun bindViewModelFactory(factory: UserViewModelFactory):
        ViewModelProvider.Factory
}
Rup
  • 33,765
  • 9
  • 83
  • 112

2 Answers2

6

Add a qualifier to your provider methods:

@Binds
@Named("Auth")
internal abstract fun bindViewModelFactory(factory: AuthViewModelFactory): ViewModelProvider.Factory

@Binds
@Named("User")
internal abstract fun bindViewModelFactory(factory: UserViewModelFactory): ViewModelProvider.Factory

And here is the tricky part: when injecting, you have to use the following syntax:

@Inject
@field:Named("Auth")
internal lateinit var factory: ViewModelProvider.Factory

@Inject
@field:Named("User")
internal lateinit var factory: ViewModelProvider.Factory
Benjamin
  • 7,055
  • 6
  • 40
  • 60
  • But why? what does the @field: do here? – Moh Mah Apr 08 '19 at 12:54
  • In kotlin a var is composed of: a getter method, a setter method and a field, so you needed to directly address field with your annotation. This requirement has been removed in later versions of Dagger though. – kassim Mar 18 '21 at 14:33
0

You can inject a @Named into a kotlin activity like this:

@JvmField
@Inject
@field:Named("PARAMETER_NAME")
var something: Boolean = false

or like this for non primitive values:

@JvmField
@Inject
@field:Named("PARAMETER_NAME")
lateinit var something: SomeType
Luiz Filipe Medeira
  • 1,142
  • 8
  • 13