I'm having trouble migrating a project from Dagger to Hilt.
The legacy code uses a class Foo that has configuration for the app itself (like country code and such), an instance of this Foo class is retrieved after the user chooses a region from a button that triggers an async call.
This Foo instance is used to create a FooModule and is assigned to the dependency graph as follows:
override fun onFooReceived(foo: Foo) {
DaggerFooComponent.Builder()
.fooModule(FooModule(foo))
.mainAppComponent(appComponent)
.build()
}
Also, this Foo class is used to create a Factory class that returns instances of different classes (like RetrofitApiClients) depending on properties of said foo class.
The FooModule class looks something like this:
@Module
class FooModule(private val foo: Foo) {
@Provides
fun provideFoo(): Foo = foo
@Provides
fun provideRetrofitClient(): RetrofitClient = foo.factory.getRetrofitClient(foo)
@Provides
fun provideOtherClass(): OtherClass = foo.factory.getOtherClass(foo)
}
The FooFactory class is just an interface with different implementations that instanciate classes dependending on Foo properties.
interface FooFactory {
fun getOtherClass(foo: Foo): OtherClass
fun getRetrofitClient(foo: Foo): RetrofitClient
}
implementations looks like follow:
class NorthRegionFooFactory: FooFactory {
override fun getOtherClass(foo: Foo) = OtherClass(foo.regionId)
override fun getRetrofitClient(foo: Foo) = RetrofitClient(foo.getConfig("base_url_key"))
}
class SouthRegionFooFactory: FooFactory {
override fun getOtherClass(foo: Foo) = throw Exception("OtherClass not supported in this region")
override fun getRetrofitClient(foo: Foo) = RetrofitClient(SOUTH_REGION_MOCK_CONSTANT)
}
What I tried so far
What came to my mind to solve this was @AssistedInject, I modified the code to look like this:
FooModule:
@Module
@InstallsIn(SingletonComponent::class)
class FooModule @AssistedInject constructor(@Assisted val foo: Foo) {
@Provides
fun provideFoo(): Foo = foo
@Provides
fun provideRetrofitClient(): RetrofitClient = foo.factory.getRetrofitClient(foo)
@Provides
fun provideOtherClass(): OtherClass = foo.factory.getOtherClass(foo)
}
FooModuleFactory (new class)
@AssistedFactory
interface FooModuleFactory {
fun create(foo: Foo): FooModule
}
And when receiving the Foo instance...
SelectRegionActivity
@AndroidEntryPoint
class SelectRegionActivity: AppCompatActivity {
@Inject
lateinit var fooModuleFactory: FooModuleFactory
override fun onFooReceived(foo: Foo) {
fooModuleFactory.create(foo)
}
}
but this doesn't work because Hilt needs empty constructor for modules:
public final class FooModule {
^
Modules that need to be instantiated by Hilt must have a visible, empty constructor.
[Hilt] Processing did not complete. See error above for details.
I tried adding the @Assisted Foo constructor as a secondary constructor for FooModule and havign the primary constructor empty but I get the same error.
Is possible to have @Assisted properties within Hilt modules?