我是Dagger的新手(Android版本2.16),根据我的阅读情况,据我所知,对于某个组件,应该有一个提供程序(@Provides
或@Binds
)封装在一个模块(@Module
)。通过大量的示例,我看到代码中包含一些在任何模块中都没有提供的对象,也没有使用new进行实例化。
我的理解是,为了访问模块中的依赖项,使用者类需要将自己注入到组件图中(组件通常提供一种注入类的方法)。代码示例也没有这样做。
Here's some code展示了我的担忧。 <{3}}未在任何模块中提供,但仍RecipePresenter正在使用它。
我能想到的一个可能的解释是@Inject
,除了请求依赖项之外,还将请求类(链接代码中的RecipePresenter
)添加/注入到组件图中。但假设有多个组件/子组件,哪个组件使用@Inject
构造函数的类是否附加到? 如果我的理解是正确的,为什么活动和片段必须在组件中手动注入 - 如果它们声明一个用@Inject
注释的变量,它们是否应该自动注入?
答案 0 :(得分:1)
RecipePresenter有一个@Inject
- 带注释的构造函数,允许它被提供。 RecipeActivity中@Inject
字段上的recipePresenter
注释没有帮助,只有@Inject
- 带注释的构造函数。
class RecipePresenter @Inject constructor(
private val useCase: RecipeUseCase,
private val res: StringRetriever) :
RecipeUseCase.Callback {
使用
@Inject
注释Dagger应该用来创建类实例的构造函数。当请求新实例时,Dagger将获取所需的参数值并调用此构造函数。
如果带有@Inject
注释构造函数的类也具有已定义的scope,则绑定将仅影响具有相同范围注释的组件:@ActivityScope
类不会#39;例如,可以从@Singleton
组件访问。如果类没有定义范围,那么绑定可以出现在需要它的任何和所有组件上,这很好:实现总是相同的,由构造函数本身定义。
@Inject
根据其注释内容有不同的含义:
@Inject
注释某个字段时,它表示DI系统应根据DI系统的值在注入该对象时设置该字段。@Inject
注释方法时,它表示DI系统应该使用基于DI系统的值的参数调用该方法,当注入该对象时。@Inject
注释构造函数时,表示允许DI系统调用该构造函数以创建该对象(触发上面的字段和方法注入) 。从这个意义上讲,它确实像内置的提供商一样。在Dagger中,@Provides
方法优先于@Inject
构造函数(如果它们都存在于同一个类中),并且与JSR-330规范不同,Dagger需要@Inject
- 即使没有其他构造函数存在,也可以使用带注释的构造函数。来自Dagger用户指南:
如果您的班级有
@Inject
- 带注释的字段但没有@Inject
- 带注释的构造函数,Dagger会在请求时注入这些字段,但不会创建新实例。添加带有@Inject
注释的无参数构造函数,以指示Dagger也可以创建实例。Dagger无法构建缺少
@Inject
注释的类。
最后,回答你关于为什么活动和片段需要注入自己的问题:允许Android在没有Dagger帮助或参与的情况下反射性地创建Activity / Fragment / View对象。这意味着没有任何内容触发上述字段和方法注入,直到您调用a members-injection method on the component指示Dagger填充这些字段并调用这些方法。因此,您永远不会在Android中的应用程序,活动,服务,片段,视图,ContentProvider和BroadcastReceiver子类上看到@Inject
- 带注释的构造函数:Android将忽略@Inject
注释,因此您可能也应该如此自己控制注射,手动或通过dagger.android。