faritowich
faritowich

Reputation: 173

How to create two objects in Dagger Hilt with different life scopes?

I have a repository that should be Singletone as it holds state inside it. I provide it like this:

@Module
@InstallIn(SingletonComponent::class)
object RepoModule {

 @Provides
    fun provideMyRepository(/* Deps */): MyRepository = MyRepositoryImpl( /* Deps */ )
}

And there is a UseCase that is only used in some ViewModel and I want it to live as long as ViewModel does. So I want create it as ViewModelComponent:

@Module
@InstallIn(ViewModelComponent::class)
object ViewModelModule {

 @Provides
    fun provideMyUseCase(myRepo: MyRepository): MyUseCase = MyUseCase(myRepo=myRepo)
}

The problem is that I cannot create this UseCase as ViewModelComponent because it should have the same Component as all its dependencies do. So if MyRepository is provided as Singletone, MyUseCase should be provided the same way.

How can I handle this problem? I can just make MyUseCase singlotone too and Hilt will build the project, but I don't want MyUseCase to exist all the time application lives.

Upvotes: 0

Views: 36

Answers (1)

Jan Itor
Jan Itor

Reputation: 4276

Both of your bindings are actually unscoped. Per hilt docs:

Warning: A common misconception is that all bindings declared in a module will be scoped to the component the module is installed in. However, this isn’t true. Only bindings declarations annotated with a scope annotation will be scoped.

So you should add scoping annotations to the providing methods:

@Provides
@Singleton
fun provideMyRepository(/* Deps */): MyRepository = MyRepositoryImpl( /* Deps */)

and

@Provides
@ViewModelScoped
fun provideMyUseCase(myRepo: MyRepository): MyUseCase = MyUseCase(myRepo = myRepo)

So if MyRepository is provided as Singletone, MyUseCase should be provided the same way.

Why? You can provide MyUseCase per ViewModel with the same singletone MyRepository instance.

Also, if all of the MyUseCase dependencies are provided by Hilt, you can avoid using a Module by using constructor based injection:

@ViewModelScoped
class MyUseCase @Inject constructor(
    val myRepo: MyRepository,
) {
}

Upvotes: 0

Related Questions