所以,我目前正在重新设计我的一个 Android 应用程序以使用Dagger。我的应用程序又大又复杂,我最近遇到了以下情况:
对象 A 需要一个特殊的 DebugLogger 实例,它是注入的完美候选者。我可以通过 A 的构造函数注入它,而不是传递记录器。这看起来像这样:
class A
{
private DebugLogger logger;
@Inject
public A(DebugLogger logger)
{
this.logger = logger;
}
// Additional methods of A follow, etc.
}
到目前为止,这是有道理的。但是,A需要由另一个类B来构造。必须构造多个A的实例,所以按照Dagger的做事方式,我简单地将aProvider<A>
注入B:
class B
{
private Provider<A> aFactory;
@Inject
public B(Provider<A> aFactory)
{
this.aFactory = aFactory;
}
}
好的,到目前为止很好。但是等等,突然 A 需要额外的输入,例如一个称为“数量”的整数,这对其构造至关重要。现在,我的 A 构造函数需要如下所示:
@Inject
public A(DebugLogger logger, int amount)
{
...
}
突然,这个新参数干扰了注射。此外,即使这确实有效,我也无法在从提供者检索新实例时传递“金额”,除非我弄错了。我可以在这里做几件事,我的问题是哪一个是最好的?
setAmount()
我可以通过添加一个预期在构造函数之后调用的方法来重构 A。然而,这很丑陋,因为它迫使我延迟 A 的构建,直到填写“数量”。如果我有两个这样的参数,“数量”和“频率”,那么我将有两个设置器,这意味着要么复杂的检查以确保在调用两个 setter 后恢复 A 的构造,否则我将不得不在组合中添加第三种方法,如下所示:
(Somewhere in B):
A inst = aFactory.get();
inst.setAmount(5);
inst.setFrequency(7);
inst.doConstructionThatRequiresAmountAndFrequency();
另一种选择是我不使用基于构造函数的注入,而是使用基于字段的注入。但是现在,我必须公开我的领域。这不适合我,因为现在我有义务将我的班级的内部数据透露给其他班级。
到目前为止,我能想到的唯一有点优雅的解决方案是对提供者使用基于字段的注入,如下所示:
class A
{
@Inject
public Provider<DebugLogger> loggerProvider;
private DebugLogger logger;
public A(int amount, int frequency)
{
logger = loggerProvider.get();
// Do fancy things with amount and frequency here
...
}
}
即使如此,我也不确定时机,因为我不确定 Dagger 是否会在调用我的构造函数之前注入提供程序。
有没有更好的办法?我只是错过了有关 Dagger 工作原理的一些信息吗?