Reputation: 13668
Without using FragmentFactory
, scoping dependencies within Fragment is straigth forward. Just create a Subcomponent
for your fragment and just create the Fragment
's Subcomponent in onAttach()
.
But when using FragmentFactory
you no longer inject dependencies via the subcomponent but instead pass then in Fragment
's constructor.
I was wondering if I could still declare a dependency which should only last within the fragment's lifecycle using Dagger
. I currently could not think of a way to achieve this.
So instead of binding my dependencies to a certain scope, I just declare the dependency with any scope or just use @Reusable
on them.
Also, since fragments are created through FragmentFactory
, the created Fragments
doesn't exist in the DI graph.
How can we properly scope dependencies to fragment and also be able to add the fragment in the DI graph when using FragmentFactory
?
Upvotes: 1
Views: 1108
Reputation: 3435
You can accomplish this by making a Subcomponent
responsible for creating your Fragment
. The Fragment
should have the same scope as this Subcomponent
.
@Subcomponent(modules = [/* ... */])
@FragmentScope
interface FooSubcomponent {
fun fooFragment(): FooFragment
@Subcomponent.Factory
interface Factory {
fun create(): FooSubcomponent
}
}
After taking care of any cyclic dependency issues, this Subcomponent
acts the same as if you had explicitly created a subcomponent in onAttach()
using @BindsInstance
, except that you can (and must) now use constructor injection on FooFragment
.
In order to provide FooFragment
in your main component (or parent subcomponent), you will need to install this Subcomponent
into a module.
@Module(subcomponents = [FooSubcomponent::class])
object MyModule {
@Provides
@IntoMap
@FragmentKey(FooFragment::class)
fun provideFooFragment(factory: FooSubcomponent.Factory): Fragment {
return factory.create().fooFragment()
}
}
Some caveats:
The scenario you describe (FooFragment
depends on some class which depends on FooFragment
) is the definition of a cyclic dependency. You will need to inject a Lazy
or Provider
at some point in this cycle, or Dagger will throw an error at compile time.
If you split this up into two steps, first providing FooFragment
and then binding it into your map, the subcomponent will see the @Provides
method from its parent component. This is likely to cause a StackOverflowError
if you aren't careful.
Upvotes: 2