My software specifications are as follows:
Android Studio 3.4
dagger-android 2.16
I have the following class that passes a MapboxGeocoder
that will execute and return a response.
class GeocodingImp(private val mapboxGeocoder: MapboxGeocoder) : Geocoding {
override fun getCoordinates(address: String, criteria: String): AddressCoordinate {
val response = mapboxGeocoder.execute()
return if(response.isSuccess && !response.body().features.isEmpty()) {
AddressCoordinate(
response.body().features[0].latitude,
response.body().features[0].longitude)
}
else {
AddressCoordinate(0.0, 0.0)
}
}
}
However, the MapboxGeocoder
is generated in a dagger module at compile time. So I have to specify the string for the address and TYPE_ADDRESS
.
@Reusable
@Named("address")
@Provides
fun provideAddress(): String = "the address to get coordinates from"
@Reusable
@Provides
@Named("geocoder_criteria")
fun provideGeocoderCriteria(): String = GeocoderCriteria.TYPE_ADDRESS
@Reusable
@Provides
fun provideMapboxGeocoder(@Named("address") address: String, @Named("geocoder_criteria") geocoderCriteria: String): MapboxGeocoder =
MapboxGeocoder.Builder()
.setAccessToken("api token")
.setLocation(address)
.setType(geocoderCriteria)
.build()
@Reusable
@Provides
fun provideGeocoding(mapboxGeocoder: MapboxGeocoder): Geocoding =
GeocodingImp(mapboxGeocoder)
my component
class:
interface TMDispatchMobileUIComponent {
@Component.Builder
interface Builder {
@BindsInstance
fun application(application: TMDispatchMobileUIApplication): Builder
fun build(): TMDispatchMobileUIComponent
}
fun inject(application: TMDispatchMobileUIApplication)
}
In the main activity I would use this like this as the user can enter in a different address or change the criteria to something else. But as the module are compiled I cannot pass any parameters to them at runtime:
presenter.getAddressCoordinates("this should be the actual address", GeocoderCriteria.TYPE_ADDRESS)
For my injection into the Activity I use the following:
AndroidInjection.inject(this)
Is there any solution to this problem?
The problem you have can be solved using "Assisted injection" approach.
It means that you need a class to be built both using dependencies provided from the existing scopes and some dependencies from the instance's creator, in this case, your main activity. Guice from Google has a nice description of what it is and why it is needed
Unfortunately, Dagger 2 does not have this feature out from the box. However, Jake Wharton is working on a separate library that can be attached to Dagger. Moreover, you can find more details in his talk on Droidcon London 2018, where he dedicated a whole talk section for this question: https://jakewharton.com/helping-dagger-help-you/