Is it possible to have a scoped child component th...
# kotlin-inject
e
Is it possible to have a scoped child component that narrows the scope for a dependency? Example in thread.
In this example,
ChildScreen.bar
will be created by getting an instance of
Foo
from the parent component. Is there a way to have
ChildScreenComponent
have its own scoped value for
Foo
that is separate from the one in
ParentScreenComponent
?
Copy code
@Scope
annotation class ScreenScope

@ScreenScope
@Inject
class Foo

class ParentScreen {
  private val component = ParentScreenComponent::class.create()

  private val childScreen by lazy {
    component.childScreen
  }
}

@ScreenScope
@Component
abstract class ParentScreenComponent {
  abstract val childScreen: ChildScreen

  @ScreenScope
  @Provides
  fun parentComponent() = this
}

@Inject
class Bar(foo: Foo)

@Inject
class ChildScreen(
  private val parentComponent
) {
  private val childComponent = ChildScreenComponent::class.create(parentComponent)
  private val bar: Bar by lazy {
    childComponent.bar
  }
}

@ScreenScope
@Component
abstract class ChildScreenComponent(
  @Component val parentComponent: ParentScreenComponent
) {
  abstract val bar: Bar
}
e
My assumption would be this would be a compile error to have the child and parent component have the same scope as it's not clear where it should come from. It's certainly possible that that check is missing though.
e
Looks like there's no compiler error. So the expectation is that if I want each screen (using the example from above) to have its own scope, it would have to have a separate scope annotation? And that if I wanted to have a class like
Bar
bound in multiple scopes, I should not put the scope or inject annotation on
Bar
itself, but define typealiases and do it there?
e
So the expectation is that if I want each screen (using the example from above) to have its own scope, it would have to have a separate scope annotation?
yes, if there's a parent-child relationship between the components. You are free to share the same scope annotation on sibling components for example.
And that if I wanted to have a class like
Bar
bound in multiple scopes, I should not put the scope or inject annotation on
Bar
itself, but define typealiases and do it there?
yeah that would work. Basically the scope tells which component 'holds' the dependency. You can see how it would be confusing if both child and parent component said they were holding it. Much in the same way it is if both child and parent component were to provide the dependency.
I'll double-check what dagger does but I'm pretty confident is works in the same way
e
OK framed that way it makes sense. In Kodein the scope is defined by a "key" (i.e. an object) that you use to retrieve the dependency. Very different model 😵
e
e
So the relevant part for me from the Dagger docs you linked is:
(Types with 
@Inject
 constructors may also be annotated with scope annotations. These “implicit bindings” may be used by any component annotated with that scope or any of its descendant components. The scoped instance will be bound in the correct scope.)
When it says "bound in the correct scope" that means it will be bound by the component that has the scope annotation? (also just checking but the equivalent of a subcomponent is a component that has a property annotated with
@Component
)?
e
When it says "bound in the correct scope" that means it will be bound by the component that has the scope annotation?
yep! I do eventually want to have our own docs on this, but for now been pointing people to dagger as scope concept is the same.
(also just checking but the equivalent of a subcomponent is a component that has a property annotated with
@Component
)?
more-or-less. Dagger actually has two ways of declaring a component relationship, subcomponents and component dependencies, kotlin-inject's ends up being a hybrid of the two.
e
OK thanks, that's helpful to know.