我在几周前开始研究Dagger 2时,也有和你一样的问题。我发现这个问题(以及其他大多数与Dagger 2相关的问题)都很难找到信息,所以我希望这可以帮到你!
最基本的答案是不行。你要找的是被称为“辅助注入”的东西,它不是Dagger 2的一部分。某些其他依赖注入(DI)框架,如
Guice,提供了这个功能,因此你可以考虑使用它们。当然,仍然有方法可以使用Dagger 2实现你想做的事情。
工厂、工厂、工厂
与DI结合使用实现你想做的事情的标准方法是使用工厂模式。基本上,你创建一个可注入的工厂类,该类将运行时参数(例如
address
)作为其提供的对象创建方法的参数。
在您的情况下,您需要一个
UtilFactory
,Dagger 2会在实例化时注入一个
Validator
,并提供一个
create(String address)
方法来创建
Util
的实例。
UtilFactory
应该保留对
Validator
的注入实例的引用,以便它在
create
方法中拥有创建
Util
实例所需的所有内容。
为许多这样的工厂编写代码可能很麻烦。 您应该确实看一下
AutoFactory,它可以减轻一些负担。 Guice的辅助注入似乎与Dagger 2 + AutoFactory非常相似(尽管具有更好的语法糖)。
更多模块/组件
我怀疑在这种情况下您可能不想这样做,但是您可以创建一个提供地址(并实例化新组件)的模块。您不必为每个可能的地址创建新的@Module类。相反,您可以将地址作为参数传递给模块的构造函数。您可以使用@BindsInstance注释,如teano建议,以实现类似的结果。
我不确定这是否是反模式。对我来说,在某些情况下,这似乎是可接受的路线,但仅当您实际上将同一地址用于“许多”对象的初始化时才是如此。您绝对不想为需要注入的每个对象都实例化新的组件和新的模型。这不是高效的,如果您不小心,您最终会比没有Dagger时拥有更多的样板代码。
不要(总是)使用DI:Injectables versus newables
在学习依赖注入(DI)框架时,对我非常有用的一点是意识到使用DI框架并不意味着您必须DI来初始化所有对象。作为一个经验法则:注入您在编译时知道并且与其他对象具有静态关系的对象; 不要注入运行时信息。
我认为this是这个主题的好文章。它介绍了“可注入”和“新建”概念。
- 可注入是DI图中靠近根部的类。这些类的实例是您期望DI框架提供和注入的对象类型。管理器或服务类型的对象是典型的可注入示例。
- 新建是DI图边缘或根本不是DI图的对象。整数,地址等是新建的示例。
总的来说,Newables 是被动对象,注入或模拟它们是没有意义的。它们通常包含应用程序中仅在运行时可用的“数据”(例如您的地址)。Newables 不应保留对 injectables 的引用,反之亦然(这是作者所称的“injectable/newable-separation”)。
实际上,我发现清楚地区分 injectables 和 newables 并不总是容易或可能的。尽管如此,我认为它们是作为思考过程的一部分使用的好概念。在向项目添加另一个工厂之前,请三思而后行!
在您的情况下,我认为将 Util 视为 injectable,将地址视为 newable 是有意义的。这意味着地址不应是 Util 类的一部分。如果您想使用 Util 的实例进行验证/... 地址等操作,请将要验证的地址作为参数传递给验证/... 方法。
2021 年更新
自Dagger 2.31版本以来,还有一种使用@AssistedInject
进行辅助注入的机制。您可以在此处文档中了解更多信息(在Jay Sidri的建议下进行编辑)。
Util
所需的特定依赖关系并不会改变。如果您认为类的依赖关系过多,那可能意味着它们耦合过紧。 - Semafoor