dependency-injectionmoduledagger-2daggersubcomponent

Why is using @Module.subcomponents better than installing a subcomponent via a method on the parent component?


From the docs:

Using @Module.subcomponents is better since it allows Dagger to detect if the subcomponent is ever requested. Installing a subcomponent via a method on the parent component is an explicit request for that component, even if that method is never called. Dagger can’t detect that, and thus must generate the subcomponent even if you never use it.

Does anyone understand exactly what does that mean?


Solution

  • Dagger can't tell whether any of your component methods are ever called: It is a compile-time framework that generates a component implementation, and it implements every method you put on your component interface.

    @Component(modules = YourModule.class)
    public interface YourComponent {
      ClassA a();
      ClassB b();
    
      ExplicitSubcomponent createExplicitSubcomponent(Dep1 dep1, Dep2 dep2);
    }
    
    @Module(subcomponents = ImplicitSubcomponent.class)
    public abstract class YourModule {
      @Binds ClassC classC(DefaultClassC classCImpl);
    }
    

    In the above example we have ClassA, ClassB, and ClassC. Let's say that out of all of those, you only actually need ClassA: They don't actually depend on each other, and you don't actually use the subcomponents.

    This illustrates Dagger's philiosophy of only compiling what is reachable from the component interface itself. This applies to subcomponents, too:

    Of course, if you're trimming your build with Proguard or some other static analyzer, those tools might be able to trim unnecessary classes or methods. However, at that point you're doing work to codegen the subcomponent, you're doing work to compile that into bytecode, and then Proguard is doing work to remove it. It is much more efficient in large projects if you avoid compiling the subcomponent until you know you need it, which Module.subcomponents enables.