Trying to grok Dagger 2 and having an issue with named providers. I have a simple setup as follows:
// Module
@Module
class AppModule(private val app: App) {
@Provides @AppScope fun providesApp() = app
@Provides @AppScope fun provideSharedPreferences(app: App) = PreferenceManager.getDefaultSharedPreferences(app)
@Provides @AppScope @Named("Uri1") fun providesUri1() = Uri.Builder().scheme("https").authority("authory1").build()
@Provides @AppScope @Named("Uri2") fun providesUri2() = Uri.Builder().scheme("https").authority("authory2").build()
}
// Component
@AppScope
@Component(modules = arrayOf(AppModule::class))
interface AppComponent {
fun inject(target: MainActivity)
}
// MainActivity
@Inject @AppScope lateinit var preferences: SharedPreferences
@Inject @AppScope @Named("Uri1") lateinit var uri1: Uri
@Inject @AppScope @Named("Uri2") lateinit var uri2: Uri
When rebuilding my project I am given:
Error:Gradle: android.net.Uri cannot be provided without an @Provides- or @Produces-annotated method.
I don't understand why adding the Named qualifier doesn't work for me here. If I remove these I can get an instance of SharedPreferences without issue.
Any insight into what I'm doing wrong would be appreciated!
Changes per suggestions with the same results as above.
// New module
@Module
class AppModule(private val app: App) {
@Provides @AppScope fun providesApp() = app
@Provides @AppScope fun provideSharedPreferences(app: App) = PreferenceManager.getDefaultSharedPreferences(app)
@Provides @AppScope @Tag("Uri1") fun providesUri1(): Uri = Uri.Builder().scheme("https").authority("authority1").build()
@Provides @AppScope @Tag("Uri2") fun providesUri2(): Uri = Uri.Builder().scheme("https").authority("authority2").build()
}
// Tag annotation
@Qualifier
@Retention(AnnotationRetention.RUNTIME)
annotation class Tag(val tag: String = "")
// MainActivity
@Inject @AppScope lateinit var preferences: SharedPreferences
@Inject @AppScope @Tag("Uri1") lateinit var uri1: Uri
@Inject @AppScope @Tag("Uri2") lateinit var uri2: Uri
Project Repo @ Github
Dagger 2 is the first to implement the full stack with generated code. The guiding principle is to generate code that mimics the code that a user might have hand-written to ensure that dependency injection is as simple, traceable and performant as it can be.
Dagger automatically generates code that mimics the code you would otherwise have hand-written. Because the code is generated at compile time, it's traceable and more performant than other reflection-based solutions such as Guice. Note: Use Hilt for dependency injection on Android.
Dagger 2 is a compile-time android dependency injection framework that uses Java Specification Request 330 and Annotations. Some of the basic annotations that are used in dagger 2 are: @Module This annotation is used over the class which is used to construct objects and provide the dependencies.
Apart from the @Inject annotation, there's another way to tell Dagger how to provide an instance of a class: the information inside Dagger modules. A Dagger module is a class that is annotated with @Module . There, you can define dependencies with the @Provides annotation. Kotlin Java.
I think I found the problem (at least I checked out your project and it generated dagger classes correctly). If you need to inject fields annotated with @Named
or some @Qualifier
annotation you have to use this kind of syntax:
class MainActivity : AppCompatActivity() {
@Inject lateinit var preferences: SharedPreferences
@Inject @field:[Named ("Uri1")] lateinit var uri1: Uri // for @Named annotation or...
@Inject @field:Uri2 lateinit var uri2: Uri // ...for @Qualifier annotation
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
app().component.inject(this)
println(uri1)
println(uri2)
}
}
Notice how @Named
/ qualifier annotation goes inside @field:
(without @
itself).
Idea borrowed from this repo.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With