使用Dagger 2进行方法注入
问题内容:
在使用Dagger 2进行方法注入方面,我还没有找到很好的解释/示例。有人可以帮我理解吗?
例:
@Inject
public Dinner makeDinner(Pasta pasta, Sauce sauce) {
mPan.add(pasta);
mPan.add(sauce);
return mPan.cookDinner();
}
因此,如果用注释我的方法@Inject
,是否可以正确地假定方法签名中的参数将注入对象图中定义的对象?那我该如何在代码中使用这种方法呢?当我进行方法调用时,仍然希望我提供所有参数,这将达到目的。
更新:
因此,据我了解DinnerComponent.dinner()
,假设我的DinnerComponent的设置如下,则如果我调用,Dinner对象将可用:
@Component(modules = DinnerModule.class)
public interface DinnerComponent {
Dinner dinner();
}
我的DinnerModule设置如下:
@Module
public class DinnerModule {
public DinnerModule() {}
@Provides
Pasta providePasta() { return new Pasta(); }
@Provides
Sauce provideSauce() { return new Sauce(); }
}
如果我要炸晚餐怎么办?因此,让我们介绍一下这种方法:
@Inject
public Dinner makeDinner(Pasta pasta, Sauce sauce) {
mPan.add(pasta);
mPan.add(sauce);
return mPan.fryDinner();
}
我如何在组件中指定哪一顿晚餐?
问题答案:
方法注入的一个根本区别与您似乎使用的方法不同,它是
方法注入只是Dagger
在构造或注入DI就绪对象时发送依赖项的另一种方法
,这意味着 @Inject注释的方法是意味着Dagger在构建时会被调用,而不是在您自己的代码中调用
。这使得@Inject
-annotate
makeDinner
,fryDinner
或任何其他具有有意义的副作用或返回值的方法的可能性非常小。相反,将方法注入视为构造函数式注入的事后机会。
public class Chef {
private Provider<Pasta> mPastaProvider;
private Sauce mSauce;
@Inject
public void registerIngredients( // can be named anything
Provider<Pasta> pastaProvider,
Sauce sauce) { // T and Provider<T> both work, of course
mPastaProvider = pastaProvider;
mSauce = sauce;
}
/* Non-@Inject */ public Dinner cookDinner() {
mPan.add(mPastaProvider.get());
mPan.add(mSauce);
return mPan.cookDinner();
}
/* Non-@Inject */ public Dinner fryDinner() {
mPan.add(mPastaProvider.get());
mPan.add(mSauce);
return mPan.fryDinner();
}
}
在这种情况下,当您请求在Chef上进行注入时,Dagger将看到@ Inject-
annotated方法并对其进行调用。除非您具有@Inject注释的构造函数或@Provides方法,否则您将无法直接从Component获取Chef,但是
可以void
在Component上创建一个方法,该方法接收构造的Chef
实例并使用字段和方法注入为厨师提供他们可能需要的食材(或食材供应商)。(有关详细信息,请参见@Component和MembersInjector文档。)
请注意,在任何情况下Dinner
对象图都不会显示!在构造函数中添加@Inject告诉Dagger它可以使用该构造函数使对象在对象图上可用,但是在方法或字段中添加@Inject只是告诉Dagger作为注入过程的一部分,它应该填充该字段或调用具有给定依赖性的该方法。如果要在对象图上提供Dinner,则需要@
Inject-Annotation Dinner构造函数,或将@Provides或@Binds方法放在要馈入组件的模块上。
你为什么要用这个?考虑一种情况,其中对象是以反射方式创建的(例如,Android中的“活动”,“片段”和“视图”,或“可序列化的”对象),而您不希望公开@Inject字段。在这些情况下,可以通过在字段上进行注入来解决构造函数约束。同样,尽管我没有尝试过,但是您可以利用类层次结构来使用@Inject标记接口方法,以确保无论您是否在DI上下文中,都可以将某些依赖项作为对象的一部分传递给对象制备。