'Dagger hilt predefined components for non android scopes
I have the following module that is used in the data layer of my application which is a plain Android Library.
@Module
interface MapperModule {
@Binds
fun bindDomainToDataMapper(domainToDataMapperImp: DomainToDataMapperImp)
: DomainToDataMapper<TodoTaskEntity, ToDoTaskModel>
@Binds
fun bindDataToDomainMapper(dataToDomainMapperImp: DataToDomainMapperImp)
: DataToDomainMapper<ToDoTaskModel, TodoTaskEntity>
}
I am just wondering what the @InstallIn scope should be as this is the Data Layer so is not specific to any android components.
I was thinking of using @InstallIn(SingleComponent::class)
but I don't want these classes to be singleton.
Any ideas of what this should be?
Solution 1:[1]
Hilt has predefined components for Android that are managed for you. However, there may be situations where the standard Hilt components do not match the object lifetimes or needs of a particular feature
Custom component limitations
Custom component definitions currently have some limitations:
Components must be a direct or indirect child of the SingletonComponent. Components may not be inserted between any of the standard components. For example, a component cannot be added between the ActivityComponent and the FragmentComponent.
To create a custom Hilt component, create a class annotated with @DefineComponent. This will be the class used in @InstallIn annotations.
The parent of your component should be defined in the value of the @DefineComponent annotation. Your @DefineComponent class can also be annotated with a scope annotation to allow scoping objects to this component.
@DefineComponent(parent = SingletonComponent::class)
interface MyCustomComponent
A builder interface must also be defined. If this builder is missing, the component will not be generated since there will be no way to construct the component. This interface will be injectable from the parent component and will be the interface for creating new instances of your component. As these are custom components, once instances are built, it will be your job to hold on to or release component instances at the appropriate time.
Builder interfaces are defined by marking an interface with @DefineComponent.Builder. Builders must have a method that returns the @DefineComponent type. They may also have additional methods (like @BindsInstance methods) that a normal Dagger component builder may have.
@DefineComponent.Builder
interface MyCustomComponentBuilder {
fun fooSeedData(@BindsInstance foo: Foo): MyCustomComponentBuilder
fun build(): MyCustomComponent
}
While the @DefineComponent.Builder class can be nested within the @DefineComponent, it is usually better as a separate class. It may be separated into a different class as long as it is a transitive dependency of the @HiltAndroidApp application or @HiltAndroidTest test. Since the @DefineComponent class is referenced in many places via @InstallIn, it may be better to separate the builder so that dependencies in the builder do not become transitive dependencies of every module installed in the component.
For the same reason of avoiding excessive dependencies, methods are not allowed on the @DefineComponent interface. Instead, Dagger objects should be accessed via entry points.
@EntryPoint @InstallIn(MyCustomComponent::class) interface MyCustomEntryPoint { fun getBar(): Bar }
class CustomComponentManager @Inject constructor(
componentBuilder: MyCustomComponentBuilder) {
fun doSomething(foo: Foo) {
val component = componentBuilder.fooSeedData(foo).build();
val bar = EntryPoints.get(component, MyCustomEntryPoint::class.java).getBar()
// Don't forget to hold on to the component instance if you need to!
}
Conclusion: Even if you create a custom component indirectly, it will look like a Singleton.
Solution 2:[2]
Even if you use @InstallIn(SingleComponent::class)
without @Singleton
annotation these object won' t be singleton. They will be non-scoped objects, and for every request, you will have new instance for these classes.
I was thinking of using @InstallIn(SingleComponent::class) but I don't want these classes to be singleton.
It means you can use @InstallIn(SingleComponent::class)
without @Singleton
annotation.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | Arda Kazancı |
Solution 2 | rooest |