I'm having this issue:
ApplicationComponent.java:8: error: [Dagger/MissingBinding] @... java.text.SimpleDateFormat cannot be provided without an @Provides-annotated method.
Module
@Module
abstract class ApplicationModule {
@Binds
@AppContext
abstract fun application(app: App): Context
@Module
companion object {
...
@Provides
@Singleton
@CalendarPickerDateFormat
fun provideCalendarPickerDateFormat(): SimpleDateFormat {
return SimpleDateFormat("dd/MMM/yyyy", Locale.getDefault())
}
}
}
Qualifier
@Qualifier
@Retention(AnnotationRetention.RUNTIME)
annotation class CalendarPickerDateFormat
Class
@ActivityScope
class MyClass
@Inject constructor(
...,
@CalendarPickerDateFormat private val calendarDateFormat: SimpleDateFormat
) {...}
Even if I add @Target(AnnotationTarget.VALUE_PARAMETER, AnnotationTarget.FUNCTION, AnnotationTarget.PROPERTY) to the Qualifier and change the class constructor to @param:CalendarPickerDateFormat, I get the same error.
What's missing?
Possible solution
Adding @JvmStatic like:
@Provides
@Singleton
@JvmStatic
@CalendarPickerDateFormat
fun provideCalendarPickerDateFormat(): SimpleDateFormat {
return SimpleDateFormat("dd/MMM/yyyy", Locale.getDefault())
}
Solves constructor injection but not field injection:
@Inject
@CalendarPickerDateFormat lateinit var date : SimpleDateFormat
Why?
NOTE: I've tried also the @Module object class approach but I have the same outcome.
How about @field:CalendarPickerDateFormat? https://github.com/google/dagger/issues/900#issuecomment-337038961
How about
@field:CalendarPickerDateFormat? #900 (comment)
It worked! But why do Qualifiers as field injection need @field but @param can be omitted from constructor?
From the official Kotlin docs:
If you don't specify a use-site target, the target is chosen according to the
@Targetannotation of the annotation being used. If there are multiple applicable targets, the first applicable target from the following list is used:
param;property;field.
So basically, it's because param is the default target when it's not specified.
Thank you so much guys! So, as a good practice, do you always specify the target?
Since precedence sorts it out for ctor params, I wouldn't specify it there. Makes the code easier to read for others, too, as they don't really have to know about use site targets in order to understand it.
I don't use Dagger with Kotlin so can't really tell, but what if you annotate the qualifier with @Target(VALUE_PARAMETER, FUNCTION, FIELD)? (same as you tried, except FIELD instead of PROPERTY) Then the precedence rule above would apply the qualifier to the field and you wouldn't have to specify it explicitly.
See also https://github.com/google/dagger/issues/900#issuecomment-404382056
This should be fixed by https://github.com/google/dagger/commit/42a3a7b9a652b115feb4a8bbf9edbb9919707a81 IIUC
For me it doesn't work with @Named field injection
Hello @PaulWoitaschek,
Have you checked the lastest release?
What's new
Kotlin support
Qualifier annotations on fields can now be understood without
The need for @field:MyQualifier (646e033)
@Module object classes no longer need @JvmStatic on the
provides methods. (0da2180)
Most helpful comment
How about
@field:CalendarPickerDateFormat? https://github.com/google/dagger/issues/900#issuecomment-337038961