Using Dagger Hilt Qualifier in Firebase Project

Yusuf Gültaç
3 min readNov 23, 2023

When it comes to managing dependencies in Android, Dagger Hilt has emerged as an efficient tool. However, when it comes to using Dagger Hilt with Firebase, developers frequently stumble certain challanges that can be effectively addressed using qualifiers. In this article, I will show the significance of using qualifiers in Dagger Hilt and use it with Firebase tech.

Before we delve into the details of using qualifier annotation, let’s understand what happens if we do not use it.

enum class FirebaseCollections(val collectionName: String) {
POST("Posts"),
LIKE("Likes"),
USER("Users"),
CATEGORY("Categories")
}
@Component(modules = [UserModule::class, PostModule::class, CategoryModule::class, LikeModule::class])
@Singleton
interface AppComponent {
fun provideUsersCollectionReference() : CollectionReference

fun providePostsCollectionReference() : CollectionReference

fun provideCategoryCollectionReference() : CollectionReference

fun provideLikesCollectionReference() : CollectionReference
}
@Module
@InstallIn(SingletonComponent::class)
object PostModule {
@Provides
@Singleton
fun providePostsCollectionReference(): CollectionReference {
return FirebaseFirestore.getInstance().collection(FirebaseCollections.POST.collectionName)
}

@Provides
@Singleton
fun providePostRepository(collectionReference: CollectionReference) : PostRepository {
return PostRepositoryImpl(collectionReference)
}
}
@Module
@InstallIn(SingletonComponent::class)
object PostModule {
@Provides
@Singleton
fun providePostsCollectionReference(): CollectionReference {
return FirebaseFirestore.getInstance().collection(FirebaseCollections.POST.collectionName)
}

@Provides
@Singleton
fun providePostRepository(collectionReference: CollectionReference) : PostRepository {
return PostRepositoryImpl(collectionReference)
}
}

In this scenario, we have mutliple CollectionReference instances, each pointing to a different Firebase colleciton. If you run the code, you will face with this issue. Without qualifiers, Dagger Hilt cannot differentiate these instances which are same type. As as result, when we try to inject a CollectionReference into our class, Hilt cannot determine which one to provide, leanding to this compile-time error.

[Dagger/MissingBinding] kotlinx.coroutines.CoroutineDispatcher cannot be provided without an @Provides-annotated method.

Introducing Qualifiers

Qualifiers in Dagger Hilt help distinguish between objects of the same type but with different configurations. They are annotations that we can attach to a dependency provider method or a injection site.

  1. Let’s add qualifiers to our code:
@Retention(AnnotationRetention.BINARY)
@Qualifier
annotation class FirebaseCollectionReference(val value: FirebaseCollections)

The retention(@AnnotationRetention.Binary) annotation is used to specify that this custom qualifer does not need to be retained at runtime.

2. Attach the Qualifier to the Provider Method. This tells Hilt that this particular method provides the specific dependency.

...
interface AppComponent {
@FirebaseCollectionReference(FirebaseCollections.USER)
fun provideUsersCollectionReference() : CollectionReference
...
}

3. Attach the Qualifer the injection site. This tells Hilt which specific instance of the dependency to inject.

@Module
@InstallIn(SingletonComponent::class)
object PostModule {
@Provides
@Singleton
@FirebaseCollectionReference(FirebaseCollections.POST)
fun providePostsCollectionReference(): CollectionReference {
return FirebaseFirestore.getInstance().collection(FirebaseCollections.POST.collectionName)
}

@Provides
@Singleton
fun providePostRepository(@FirebaseCollectionReference(FirebaseCollections.POST) collectionReference: CollectionReference) : PostRepository {
return PostRepositoryImpl(collectionReference)
}
}

In conclusion, managing dependencies in Android, especially when dealing with multiple instances of the same type, can be challenging. However, Dagger Hilt with its powerfull and flexible features like qualifiers, provides and efficient solution to this problem.

When used with Firebase, Hilt qualifiers allow us to differentiate between multiple collectionReference instances, thereby enabling more granular control over our dependencies. This is not only make our code cleaner and more maintainable, but also significantly reduces the likelihood of runtime errors due to incorrect dependency provision.

For more and more about dagger hilt annotations you can go and check this.

https://developer.android.com/training/dependency-injection/hilt-cheatsheet

--

--