I am building an Android app following the Clean Architecture Principles. Here is what I've got:
app module:
usecase module:
repository module:
data module:
I am trying to use Hilt for dependency injection in the app. I don't want to expose Retrofit, OkHttp etc to the app module because I don't want developers to be able to put network code in the wrong module. Remember, the app module uses ViewModel which can ONLY talk to use cases.
How do I set this up? I tried putting dagger modules in each of these modules to define injection, then in the main app module I included the module from usecase:
@Module(includes = [UseCaseModule::class])
@InstallIn(ApplicationComponent::class)
object AppModule
but this does not work as it starts to complain about not being able to find transitive dependencies in the other modules that I want to keep hidden.
A project with multiple Gradle modules is known as a multi-module project. In a multi-module project that ships as a single APK with no feature modules, it's common to have an app module that can depend on most modules of your project and a base or core module that the rest of the modules usually depend on.
Hilt provides a standard way to incorporate Dagger dependency injection into an Android application. The goals of Hilt are: To simplify Dagger-related infrastructure for Android apps. To create a standard set of components and scopes to ease setup, readability/understanding, and code sharing between apps.
TLDR: Use Hilt version 2.40+ which allows working with transitive dependencies
Since Hilt version 2.37 there's an gradle flag enableAggregatingTask
which
allows Hilt to collect transitive dependencies. The flag is enabled by default in version 2.40 and newer.
When you have your gradle modules as :app -> :usecase -> :repository -> :retrofit (external)
and assuming you use implementation
in your gradle scripts, your Retrofit
instance can still be provided and injected in :repository
module, but it won't leak into other modules.
So in case you want to encapsulate your Retrofit
in your repository module, you may create
@Module
@InstallIn(SingletonComponent::class)
object RepositoryModule {
@Provides
fun provideRetrofit(retrofitBuilder: Retrofit.Builder): YourApi = retrofitBuilder.create<YourApi>()
}
You don't need to manually include your RepositoryModule
in :app
as this is done by Hilt and the @InstallIn
annotation.
Unfortunately, Hilt uses a monolithic approach currently. This means that your app
module will have access to ALL your modules.
I don't want to expose Retrofit, OkHttp etc. to the app module because I don't want developers to be able to put network code in the wrong module.
No, you don't have to include your network-related classes in the app
module. Rather, in the data
module.
But bear in mind that the app
module will still indirectly have access to Retrofit by implementing the data
module for Hilt to work.
You can check out this post.
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