Bu yazıda Android’de dependency injection için kullandığımız Dagger2′ de yer alan @Qualifier ve @Named annotationlarından bahsedeceğim.
Neden @Named annotation ihtiyaç duyarız?
Dagger2’de kullanılmak istenen nesne @Provides annotation ile provide edilip sonrasında kullanılmak istenen yerde @Inject annotation ile inject ediliyor. Ancak @Provides annotation bir kısıtı var o da aynı tipe sahip nesneyi sadece bir kere provide edebilmesi. İşte bu probleme çözüm için @Named annotation kullanacağız. Örneğin;
| 1 | data class Car(val type: String) | 
üstteki gibi basit bir yapıda olan Car sınıfımız olsun ve type adında bir property alsın.
Biz bu sınıftan örneğin MainActivity içerisinde 2 tane nesneyi @Inject annotation kullanarak alalım.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 | class MainActivity : AppCompatActivity() {     @Inject     lateinit var sedan: Car     @Inject     lateinit var sports: Car     override fun onCreate(savedInstanceState: Bundle?) {         super.onCreate(savedInstanceState)         setContentView(...)     } } | 
CarModule.kt dosyasında da alttaki gibi provide ettiğimizi düşünün.
| 1 2 3 4 5 6 7 8 9 | @Module class CarModule {     @Provides     fun provideSedan(): Car = Car("Sedan")     @Provides     fun provideSports(): Car = Car("Sports") } | 
Compile ettiğinizde alttaki gibi bir hata ile karşı karşıya geleceksiniz.
| 1 2 | error: [Dagger/DuplicateBindings]  packagename.example.model.Car is bound multiple times: | 
Bu hatanın sebebi üstte bahsettiğim gibi @Provides annotation sadece tek bir nesneyi provide edebilmesi.  Ama gördüğünüz üzere aynı sınıftan 2 farklı nesneye ihtiyacım var ve bunları provide edebiliyor olmam gerekiyor.  Çözümü için @Named annotation kullanacağız.
CarModule.kt dosyasını alttaki gibi güncellersek;
| 1 2 3 4 5 6 7 8 9 10 11 | @Module class CarModule {     @Provides     @Named("sedan")     fun provideSedan(): Car = Car("Sedan")     @Provides     @Named("sports")     fun provideSports(): Car = Car("Sports") } | 
Bu işlemden sonra MainActivity üzerinde inject ettiğimiz değerlere yine @Named ile hangisini istediğimizi söylüyoruz.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | class MainActivity : AppCompatActivity() {     @Inject     @field:Named("sedan")     lateinit var sedan: Car     @Inject     @field:Named("sports")     lateinit var sports: Car     override fun onCreate(savedInstanceState: Bundle?) {         super.onCreate(savedInstanceState)         setContentView(...)     } } | 
Artık Dagger bunların farklı 2 nesne olduğunu anlayacak ve inject işleminde herhangi bir hata ile karşılaşmayacaksınız.
İşin biraz daha derinine inelim ve @Named annotation kaynak kodlarına bakalım. 
| 1 2 3 4 5 6 7 | @Qualifier @Documented @Retention(RUNTIME) public @interface Named {     /** The name. */     String value() default ""; } | 
Burada dikkatinizi çekmek istediğim @Qualifier annotation.
Gördüğünüz üzere @Named annotation aslında bir qualifier. Yani aslında işin temelini @Qualifier annotation oluşturuyor. 
@Qualifier javax.inject package altında geliyor ve istenilen nesneyi nitelemek(qualifiy) için kullanılıyor. Yani sizde @Qualifier sayesinde kendi custom annotation oluşturabilirsiniz.
Şimdi gelin kendi @Named annotationımızı yazalım ve adını da @CustomNamed yapalım.
Bunun için CustomNamed.kt adında bir dosya oluşturun ve alttaki kodları ekleyin.
| 1 2 3 | @Qualifier @Retention(AnnotationRetention.RUNTIME) annotation class CustomNamed(val value: String = "") | 
Bundan sonra tek yapmanız gereken @Named annotationları @CustomNamed ile değiştirmek.
Siz de ihtiyacınıza göre kendi custom qualifier larınızı oluşturabilirsiniz.
