This article will go straight to explaining how to use the @Inject, @Provides, and @Binds annotations. So I’ll skip the explanation of Dependency Injection or an introduction to Hilt. Let’s assume you already know how to use it. Let’s go!
Overview
There are 3 commonly used annotations to inject objects in Hilt:
@Inject: annotation used on the class constructor@Provides: annotation used in a Module@Binds: another annotation also used in a Module
So, when should you use each of these?
Inject
We use the @Inject annotation on any constructor where we want to inject an object, from ViewModel, Repository to DataSource. For example:
| |
This makes it easy to inject ProfileRepository into other classes, such as a ViewModel or UseCase. However, you can only use this annotation on constructors of classes you define yourself.
Provides
To overcome the above limitation—injecting objects of classes you don’t define (such as Retrofit, OkHttpClient, or a Room database)—we use @Provides. First, you need to create a @Module to hold dependencies with the @Provides annotation. For example:
| |
Since Retrofit objects are not defined by your code and are created using the Builder pattern, you can’t use the @Inject annotation and must use @Provides. Now, you can inject the ApiService interface object anywhere.
Binds
For interfaces, you can’t use the @Inject annotation because they don’t have constructors. However, if you have an interface with only one implementation (a class that implements that interface), you can use @Binds to inject that interface. Injecting interfaces instead of classes is a good practice and makes testing easier.
Back to the ProfileRepository in the @Inject section, let’s turn it into an interface and create a class that implements it. For example:
| |
The advantage of using @Binds instead of @Provides is that it reduces the amount of generated code, such as Module Factory classes. Here, you can see I still use @Inject because the constructor of ProfileRepositoryImpl still needs some parameters.
Summary
So, to summarize:
- Use
@Injectfor your own code - Use
@Providesfor third-party code - Use
@Bindsto inject interfaces, reducing unnecessary code
Reference
