为什么使用 @Module.subcomponents 比通过父组件上的方法安装子组件更好?
Why is using @Module.subcomponents better than installing a subcomponent via a method on the parent component?
来自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.
有没有人明白这是什么意思?
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);
}
在上面的示例中,我们有 ClassA、ClassB 和 ClassC。假设在所有这些中,您实际上只需要 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 不会为其生成代码。
当然,如果您 trim 使用 Proguard 或其他一些静态分析器构建您的构建,这些工具可能能够 trim 不必要的 类 或方法。但是,此时您正在努力对子组件进行代码生成,您正在努力将其编译成字节码,然后 Proguard 正在努力将其删除。如果在知道需要之前避免编译子组件,那么在大型项目中效率会更高,Module.subcomponents 启用。
来自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.
有没有人明白这是什么意思?
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);
}
在上面的示例中,我们有 ClassA、ClassB 和 ClassC。假设在所有这些中,您实际上只需要 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 不会为其生成代码。
当然,如果您 trim 使用 Proguard 或其他一些静态分析器构建您的构建,这些工具可能能够 trim 不必要的 类 或方法。但是,此时您正在努力对子组件进行代码生成,您正在努力将其编译成字节码,然后 Proguard 正在努力将其删除。如果在知道需要之前避免编译子组件,那么在大型项目中效率会更高,Module.subcomponents 启用。