Search code examples
androidkotlindependency-injectiondagger-2

@Qualifier causes: [Dagger/MissingBinding] when field injecting


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.


Solution

  • I've opened an issue in google/Daggers repo and this PR will "fix" this. Actually, this is not a bug and as zsmb13 mentioned:

    From the official Kotlin docs:

    If you don't specify a use-site target, the target is chosen according to the @Target annotation 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.

    But this PR will be very helpful to avoid this situations in the future.

    EDIT: Dagger 2.25.2 fixes it.