因此,我正在重新设计我的Android应用程序以使用Dagger。我的应用程序非常庞大复杂,最近遇到以下情况:在构造函数中使用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的多个实例必须构建构造,所以下面做事的匕首的方式,我简单的注入Provider<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的构建,直到“金额”被填充。如果我有两个这样的参数,“数量”和“频率”,那么我将有两个调整器,这意味着复杂的检查,以确保那建造重新开始制定者都被称为后,或者我会还添加第三个方法混进去,就像这样:
(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
...
}
}
即使如此,我不确定的时间,因为我m不知道在我的构造函数被调用之前Dagger是否会注入提供者。
有没有更好的方法?我是否错过了关于匕首是如何工作的?
感谢您的快速回复。你所描述的工厂模式似乎是最好的方法。我也意识到,如果Dagger支持私人领域注入,它很容易让我试图完成。我想知道为什么这不是Dagger原创设计的一部分?我假定匕首使用反射注入。如果是这样,那么私人领域应该没有问题,对吗? – Alex
匕首回落,但这不是它的主要注射方式。它会生成直接设置字段或调用构造函数的代码。因此,它与源代码树中的任何其他代码一样工作,并且无法访问“私人”成员。 –
而一些安全管理人员会打破依赖于类中可访问性的反射。 –