Dagger-Hilt Module and Provides Annotations #4
Helloo, In this article, we will talk about the Provides annotation used in modules.
The @Provides
annotation is used in the context of dependency injection frameworks, such as Hilt for Android, to declare a method that provides instances of certain dependencies. It is typically used in conjunction with the @Module
annotation to define a class that acts as a module for dependency injection.
Here’s a more detailed explanation of why the @Provides
annotation is used:
- Dependency Injection (DI): Dependency injection is a design pattern that promotes loose coupling between components in an application. It allows you to separate the creation and management of dependencies from the classes that require them. Instead of creating dependencies directly within a class, they are provided from external sources.
- Modules: In Hilt, modules are classes annotated with
@Module
that define how to create and provide instances of dependencies. They act as a configuration layer for the dependency injection framework. Modules can contain one or more methods annotated with@Provides.
- Providing Dependencies: The
@Provides
annotation is used to annotate methods within modules that are responsible for providing instances of dependencies. These methods are typically named after the dependency they provide. For example, if you have a classFoo
that requires an instance ofBar
, you can define a@Provides
method in a module that creates and returns an instance ofBar
. - Binding Annotations: In addition to
@Provides
, Hilt also supports binding annotations such as@Named
or custom annotations to differentiate between multiple@Provides
methods that provide the same type of dependency. Binding annotations help resolve conflicts when multiple dependencies of the same type are required. - Configuration and Customization: By using the
@Provides
annotation, you have control over how dependencies are created and provided. You can customize the creation logic, use different implementations based on conditions, or incorporate external libraries and services into the dependency graph.
Example
Let’s consider a scenario where we have a UserService
interface and a UserServiceImpl
class that implements it. The UserServiceImpl
requires a UserApiService
dependency to interact with a remote API. We'll use Hilt's @Provides
annotation to provide these dependencies.
First, let’s define the UserService
interface:
interface UserService {
fun getUsers(): List<User>
}
Next, we have the UserServiceImpl
class that implements the UserService
interface:
class UserServiceImpl @Inject constructor(private val userApiService: UserApiService) : UserService {
override fun getUsers(): List<User> {
// Implementation to fetch users using userApiService
// ...
}
}
Now, let’s create a Hilt module, UserModule
, to provide the necessary dependencies:
@Module
@InstallIn(ApplicationComponent::class)
object UserModule {
@Provides
fun provideUserService(userServiceImpl: UserServiceImpl): UserService {
return userServiceImpl
}
@Provides
fun provideUserApiService(): UserApiService {
return UserApiService() // Or obtain it from a network library
}
}
In the UserModule
, we define the provideUserService()
method annotated with @Provides
, which provides an instance of UserService
. We specify the concrete implementation UserServiceImpl
as a parameter.
We also define the provideUserApiService()
method annotated with @Provides
, which provides an instance of UserApiService
. In this example, we create a new instance of UserApiService
within the method, but you can also obtain it from a network library like Retrofit.
Now use in MainActivity;
@AndroidEntryPoint
class MyActivity : AppCompatActivity() {
@Inject
lateinit var userService: UserService
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// Use the injected dependency
userService.getUsers()
}
}
I hope it was useful. You can follow me on my social media accounts.