你可以配置Dagger2默认创建Component.Factory而不是Component.Builder吗?

问题描述 投票:0回答:1

我有一个由许多匕首组件组成的依赖图;分为4层,组件也依赖于父组件。

当我定义一个组件时;我配置它们的依赖项,有时只有 1 个依赖项,有时甚至最多 6 个父组件。通常这些父组件是该新组件的唯一依赖项,因此 dagger 为我创建一个 Component.Builder,我可以用它来实例化该组件。

但是,据我所知,使用 Component.Builder,您不会进行编译时检查来验证您是否在 Builder 中提供了所有要求。使用 Component.Factory,您确实可以进行编译时检查。

所以我的问题是,是否有可能使默认方法也编译时安全?例如强制 dagger 默认生成工厂类而不是构建器类?

我何时收到运行时异常而不是编译时错误的示例:

// Define 3 layers of components
@AppScope
@Component()
interface AppComponent {
    fun provisionSomething(): Something
}

@EnvironmentScope
@Component(
    dependencies = [AppComponent::class]
)
interface EnvironmentComponent {
    fun provisionEnvironment(): Environment
}

@ActivityScope
@Component(
    dependencies = [AppComponent::class, EnvironmentComponent::class]
)
interface FeatureComponent {
    fun inject(viewModel: MyViewModel)
}

// create components
fun getAppComponent(): AppComponent = TODO("not relevant for example")
fun getEnvironmentComponent(): EnvironmentComponent = TODO("not relevant for example")
fun getFeatureComponent(): FeatureComponent {
    return DaggerFeatureComponent
        .builder()
        .appComponent(getAppComponent())
        //.environmentComponent(getEnvironmentComponent()) // This will compile just fine, but crash only runtime
        .build()
}

如图所示,当你忘记更新组件的实例化时,请确保调用所有相关的构建器方法,编译时安全性就消失了。

如果我重新配置我的FeatureComponent来自己创建一个工厂,我将再次获得编译时安全性。然而,在团队中工作,我希望有一种方法可以更好地强制编译时安全;例如使用编译器标志来更改默认行为,或者可能是其他东西。

谢谢。

dagger-2
1个回答
0
投票

不,目前不支持此功能,如果它存在,则会有缺点。

首先也是最重要的:理想情况下,我们一开始就不应该依赖自动生成的构建器,更不用说工厂了。正如在 google/dagger#935 中一样,生成 API 的源代码生成器被认为比生成实现的生成器更难使用,这是影响 Dagger 设计的因素之一,即您编写接口(组件、子组件、构建器) 、工厂等),Dagger 生成它的实现。原因之一是,对于生成的接口,您的 IDE 或构建系统将需要运行源代码生成器来确定 API 表面本身;如果系统只生成实现,则仍然可以确定接口,而无需调用整个源代码生成器。 Dagger 默认情况下提供了一个 Builder,但是提供您自己的构建器(命名控件、@BindsInstance、文档、IDE 支持)的好处是强烈建议您编写自己的构建器。

还有:

  • 模块没有自然的顺序。它可以是简单的类名字母顺序、FQCN 字母顺序或完全其他的顺序。为了确定添加新模块或依赖项的顺序,您必须检查生成的代码。 (我最初也建议模块遍历顺序,深度优先或广度优先,但想象一下,如果模块顺序或传递包含要改变,参数顺序改变会有多刺耳。)

  • 模块可以是可选的,特别是对于具有默认构造函数的可实例化模块。 Factory 的当前实现要求您选择并且不支持多个工厂方法,尽管设计文档对此作为扩展开放。因此,对于工厂来说,不如对于构建器来说,有一个足够可预测的实现让 Dagger 为您编写它。

  • Builder 和 Factory 目前无法共存,如果共存,则必须跟踪它们以确保它们需要提供哪些

    @BindsInstance
    绑定的一致性。这些当前是在 Builder 或 Factory 上定义的。

  • 如果您要为构建器与工厂创建一个配置选项,因为它们当前无法共存,那么您需要为每个类详细定义它,或者为每个构建定义它,并希望没有人依赖于生成的构建器并生成工厂在同一栋楼里。 (你可以两者都做,但这会让事情变得更加复杂,特别是对于可重用的模块/组件/库。)

总而言之,自动生成的工厂会存在一些主要的可用性问题。它们目前不受支持(尽管我不是 Dagger 团队的成员,也没有以任何官方身份发言),如果它们很快得到支持,我会感到惊讶。


FWIW,我在 google/dagger 问题列表中没有找到自动生成 Factory 的功能请求,但 Factory 功能本身被提议为 google/dagger#1317 并且有一个 发布的设计文档讨论 Factory 与 Builder 的适用性和不适用性。

© www.soinside.com 2019 - 2024. All rights reserved.