15

I have a multi modular android app setup which consists of a Data, Domain and Presentation module. The Domain module is java-only. I know it's possible to support hilt in non-android modules by adding:

Domain build.gradle

implementation "com.google.dagger:hilt-core:$hilt_version"
kapt "com.google.dagger:hilt-compiler:$hilt_version"

The domain module provides implementations of UseCase classes that should be injected in the ViewModels which live in the Presentation (app)module.

Domain Module:

@Module
@InstallIn(SingletonComponent::class)
//   @InstallIn(ViewModelComponent::class)
object UseCaseModule {

    @Provides
    //    @ViewModelScoped
    fun provideGetMovieDetailsUseCase(
        movieRepository: MovieRepository
    ): GetMovieDetailsUseCase {
        return GetMovieDetailsUseCaseImpl(movieRepository)
    }
}

Presentation Module:

@HiltViewModel
class MovieDetailViewModel @Inject constructor(
    private val getMovieDetailsUseCase: GetMovieDetailsUseCase
) : ViewModel() {
    ...
}

Because of the nature of the java-only module, I can't use the @InstallIn(ViewModelComponent::class) annotation. Instead I have to install the dependency in the SingletonComponent::class. Which is also done in an awnser here

My Question

Is this approach 'best practice'? Or is it better to make the library an Android library so that I can scope the dependency to the ViewModel? I would prefer to keep it a java-only library.

Tim
  • 669
  • 1
  • 8
  • 27

2 Answers2

21

A common practice I'm aware of is moving dependency configuration for all modules to the app module (since the use of Hilt is at the framework level). You can then use the java inject library to inject dependencies in the pure java libraries (e.g domain layer).

So in your app build.gradle file, you'll have:

// hilt dependency
implementation "com.google.dagger:hilt-android:2.28-alpha"
implementation 'androidx.hilt:hilt-lifecycle-viewmodel:1.0.0-alpha02'
kapt 'androidx.hilt:hilt-compiler:1.0.0-alpha02'
kapt "com.google.dagger:hilt-android-compiler:2.28-alpha"

and in your domain build.gradle file, you'll have:

implementation "javax.inject:javax.inject:$javaInjectVersion"

In summary, the file where you "wire up" the domain module dependencies should be moved to the app module.

Here's a project that demonstrates the idea.

Tobi Daada
  • 528
  • 2
  • 8
  • 1
    ahh yes thank you, all i had to do was to move the UseCaseModule to my presentation layer. :) – Tim Jun 07 '21 at 11:27
  • 2
    if you want to use hilt in the underlying modules, you can do this with 'com.google.dagger:hilt-core' – mars8 Feb 21 '23 at 20:55
-1

This is my hit on the clean architecture and hilt

  • data is a java-only module with datasource interfaces, repository interfaces and models data
  • domain is a java-only module with usecase interfaces and entities enter image description here
  • framework is an android module where the actual implementations of datasources, repositories and usecases are found. This is the same module where the Hilt Modules are declared framework
  • app is the app module with domain and framework as dependencies
Jameido
  • 1,344
  • 1
  • 11
  • 21