I feel like I may be running into a limitation of Hilt here, but I'll try my best anyway. Basically, I'm trying to inject an instance of a generic interface where the type parameter is also an interface. A representative example of my scenario (redacted for privacy and simplicity):
interface IApi // just a base interface to identify my various Retrofit APIs
interface IApiBuilder<out T : IApi> {
fun buildApi(): T
}
interface ISomeWebsiteApi : IApi {
@GET("/endpoint/value")
suspend fun getValue(): String
}
Then I declare an implementation of IApiBuilder as so:
class SomeWebsiteApiBuilder @Inject constructor() : IApiBuilder<ISomeWebsiteApi> {
override fun buildApi(): ISomeWebsiteApi {
return Retrofit.Builder()
.someOtherConfig()
.build()
.create(ISomeWebsiteApi::class.java)
}
}
I initially tried using a binding module to inject this class into my ViewModel, as below:
@Module
@InstallIn(SingletonComponent::class)
abstract class BindsSomeWebsiteApiBuilderModule {
@Binds
@Singleton
abstract fun bindsApiBuilder(builder: SomeWebsiteApiBuilder): IApiBuilder<ISomeWebsiteApi>
}
But I get the following build error:
C:\dev\myapp\app\build\generated\source\kapt\standardDebug\com\example\myapp\MyApplication_HiltComponents.java:169: error: [Dagger/MissingBinding] com.example.myapp.IApiBuilder<? extends com.example.myapp.ISomeWebsiteApi> cannot be provided without an @Provides-annotated method.
public abstract static class SingletonC implements MyApplication_GeneratedInjector,
^
com.example.myapp.IApiBuilder<? extends com.example.myapp.ISomeWebsiteApi> is injected at
com.example.myapp.MyViewModel(�, apiBuilder)
com.example.myapp.MyViewModel is injected at
com.example.myapp.MyViewModel_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.myapp.MyApplication_HiltComponents.SingletonC ? com.example.myapp.MyApplication_HiltComponents.ActivityRetainedC ? com.example.myapp.MyApplication_HiltComponents.ViewModelC]
Due to the error message I then tried a providing module instead of binding, as below:
@Module
@InstallIn(SingletonComponent::class)
class ProvidesSomeWebsiteApiBuilderModule {
@Provides
@Singleton
fun providesApiBuilder(): IApiBuilder<ISomeWebsiteApi> = SomeWebsiteApiBuilder()
}
But I ended up with the same error message. Note that in reality, my SomeWebsiteApiBuilder has several other injected dependencies as part of this providing module.
My guess is that my issue is stemming from the fact that Hilt can't find an implementation of ISomeWebsiteApi to inject as a type parameter, but is there any way around this with Hilt? I have several Retrofit API interfaces that need building and it would be extremely convenient to be able to use this kind of architecture.
I feel like I may be running into a limitation of Hilt here, but I'll try my best anyway. Basically, I'm trying to inject an instance of a generic interface where the type parameter is also an interface. A representative example of my scenario (redacted for privacy and simplicity):
Then I declare an implementation of
IApiBuilder
as so:I initially tried using a binding module to inject this class into my ViewModel, as below:
But I get the following build error:
Due to the error message I then tried a providing module instead of binding, as below:
But I ended up with the same error message. Note that in reality, my
SomeWebsiteApiBuilder
has several other injected dependencies as part of this providing module.My guess is that my issue is stemming from the fact that Hilt can't find an implementation of
ISomeWebsiteApi
to inject as a type parameter, but is there any way around this with Hilt? I have several Retrofit API interfaces that need building and it would be extremely convenient to be able to use this kind of architecture.