I'm currently trying to figure out Dagger 2. I am trying to set up 4 scopes: App, User, Activity, Fragment. User and Activity components are Subcomponents of App. Fragment is a Component with Activity as its dependency.
Say my UserSettingsActivity needs a Toolbar (provided by ActivityModule), and a UserProfile (provided by UserModule). I won't get a UserProfile until I ask for it from the database, whereas the Toolbar can be provided right away. So the order of injection that takes place is into ActivityComponent first, then into UserComponent. I have 2 @Inject fields, one for Toolbar and one for UserProfile in the activity. I was hoping that dagger will know that the dependencies are coming from different modules, but it seems to complain that UserProfile can't be provided when injected into ActivityComponent. Obviously it can't be provided by ActivityModule, but why is it not making a connection that UserProfile is provided by UserModule?
Subcomponents work's similar to inheritance(extends), in your case User component and Activity component extending App component but there is no relation between User component and Activity component so when you request User dependency in Activity it will fail.
Subcomponent can't provide any dependency to other Subcomponent.
Instead, you can make Activity component as a subcomponent of User component. This will also give you the flexibility to switch user.
To my best knowledge, Dagger-2 doesn't support "partial injections".
Therefore, when you call
myComponent.inject(this)
, Dagger-2 throws an error ifmyComponent
can't provide all@Inject
annotated members ofthis
.I see two ways to work around this limitation:
@Inject
annotation fromUserProfile
, exposeUserProfile
via public method inUserComponent
and inject it manually whenUserComponent
is ready to be used. Something analogous to this:userProfile = userComponent.getUserProfile()
UserComponent
dependent on data fetching.UserComponent
could be used to injectToolbar
and someUserProfileProvider
at the same time, and you will fetchUserProfile
fromUserProfileProvider
when it is available.I personally think that second approach is the better choice. DI libraries should be used in order to satisfy objects' dependencies at construction time. In Android we can't construct
Activity
orFragment
ourselves, therefore we perform DI inonCreate()
,onAttach()
,onCreateView()
, etc., but it does not mean that we should be using DI libraries in order to assist in controlling the flow of applications.