为什么使用 @Module.subcomponents 比通过父组件上的方法安装子组件更好?



来自文档:

使用@Module.subcomponents更好,因为它允许 Dagger 检测是否曾经请求过子组件。通过父组件上的方法安装子组件是对该组件的显式请求,即使从未调用该方法也是如此。Dagger 无法检测到这一点,因此即使您从未使用它,也必须生成子组件。

有谁明白这到底是什么意思?

> Dagger 无法判断是否调用过任何组件方法:它是一个生成组件实现的编译时框架,它实现您放在组件接口上的每个方法。

@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);
}

在上面的例子中,我们有 A类、B 类和 C 类。假设在所有这些中,您实际上只需要 ClassA:它们实际上并不相互依赖,您实际上也不使用子组件。

  • Dagger 实现了 ClassA 和 ClassA 的依赖项传递闭包的绑定,这很好,因为你需要它!你把它放在组件接口上,以便Dagger可以为你创建实现,包括ClassA的所有依赖项。
  • Dagger 实现了 ClassB 的绑定,这不是必需的,但 Dagger 无法分辨:它只知道b()已定义,所以有一天有人可能会打电话要求 ClassB。Dagger不知道是否有人调用b(),所以它必须创建和引用ClassB的工厂实现以及ClassB传递依赖的所有内容。
  • Dagger 不会为 ClassC 实现绑定,因为即使您已绑定它,也没有人请求它。它在界面上不可用,内部也没有人要求它,所以 Dagger 可以安全地省略它。

这说明了 Dagger 的哲学,即只编译可从组件接口本身访问的内容。这也适用于子组件:

  • Dagger 为 ExplicitSubcomponent 创建了一个实现,因为与 ClassB 一样,您已将其绑定到接口上。有人可能会要求它。
  • Dagger 不会为 ImplicitSubcomponent 创建实现,直到可以从 ClassA 或 ClassB 访问它。一旦你这样做,它就会做到。如果没有人要求 ImplicitSubcomponent,Dagger 不会为其生成代码。

当然,如果要使用 Proguard 或其他静态分析器修剪构建,这些工具可能能够修剪不必要的类或方法。但是,此时你正在做代码生成子组件的工作,你正在做的工作是将其编译成字节码,然后 Proguard 正在做删除它的工作。在大型项目中,如果在知道需要子组件之前避免编译子组件,则效率会高得多,而 Module.subcomponents 支持它。

最新更新