Ad

Only One Method Can Create A Given Subcomponent Is Created By Plus()

- 1 answer

I have a Dagger Subcomponent called UserComponent, created when a user signed in to the app, beneath that I have lists of Subcomponents (e.g : FriendsComponent, ProfileComponent, HomeComponent ...).

What I want is this: creating a subComponent called ProfileComponent (under UserComponent) that got two Modules ProfileModule and PostsModule :

                         MainComponent
                             |
                =============|======================
               |                                   |
                |                                   |
          UserComponent                      WelcomeComponent
                |
       =========|============                  
       |                     |    
    ProfileComponent       HomeComponent
       |
       |
  =====================
  |                  |
 PostsModule        ProfileModule   

(I hope this is readable )

so ProfileComponent shall contains this :

@UserScope
@Subcomponent(
       modules = {PostsModule.class, ProfileModule.class}
)
public interface ProfileComponent {

   void inject(PostsFragment postsFragment);
   void inject(ProfileActivity profileActivity);
}

Here is the User SubComponent

@UserScope
@Subcomponent(
       modules = UserModule.class
)
public interface UserComponent {

           HomeComponent plus(HomeModule homeModule);

           ProfileComponent plus(PostsModule postsModule);

           ProfileComponent plus(ProfileModule profileModule);
        }

Injection done here, in PostsFragment

protected void setUpComponent(DragonBloodComponent component) {
       mApp.getApp(getActivity()).getUserComponent()
               .plus(new PostsModule())
               .inject(this);
   }

I get this error

error: Only one method can create a given subcomponent..profile.ProfileComponent is created by: [plus(PostsModule), plus(ProfileModule)]

Am I doing this right? Thank you.

Ad

Answer

ProfileComponent plus(PostsModule postsModule);
ProfileComponent plus(ProfileModule profileModule);

These two are incompatible: It looks you want to create a ProfileComponent that requires both modules, but instead you're providing two different ways to create one, and neither has both modules it needs. Dagger happens to warn you about the mutual incompatibility before it warns you that they are both incomplete.

The simplest change, as described in the "Subcomponents" section of the @Component docs, is to put them in the same method declaration (emphasis mine):

Subcomponents may also be declared via a factory method on a parent component or subcomponent. The method may have any name, but must return the subcomponent. The factory method's parameters may be any number of the subcomponent's modules, but must at least include those without visible no-arg constructors.

That would look like this:

ProfileComponent plus(PostsModule postsModule, ProfileModule profileModule);

Builders

As an alternative, define a subcomponent builder (cf. component builder) that can aggregate the modules you need. This subcomponent builder can then be injected anywhere you need it, so you don't need to inject your Component in order to call the plus method. This might also make your code more readable if you need many more modules in your subcomponent.

@UserScope
@Subcomponent(
       modules = {PostsModule.class, ProfileModule.class}
)
public interface ProfileComponent {

   void inject(PostsFragment postsFragment);
   void inject(ProfileActivity profileActivity);

   /**
    * With this you can inject a ProfileComponent.Builder from within
    * the classes that UserComponent provides, or expose it on your enclosing 
    * (sub)component if you'd like. Dagger writes the implementation.
    *
    * Of course, you can skip Modules with zero-arg constructors, because Dagger
    * doesn't need to be provided an instance of those.
    */
   @Subcomponent.Builder interface Builder {
       Builder postsModule(PostsModule postsModule);
       Builder profileModule(ProfileModule profileModule);
       ProfileComponent build();
   }
}

And consumed:

@Inject ProfileComponent.Builder profileComponentBuilder;
ProfileComponent profileComponent = profileComponentBuilder
    .postsModule(yourPostsModule)
    .profileModule(yourProfileModule)
    .build();
Ad
source: stackoverflow.com
Ad